2014-10-14 6 views
6

में पुनरावर्ती तिथियों की गणना करने का सही तरीका मेरी परियोजना में मुझे घटनाओं को दोहराने के लिए तिथियों की गणना करने की आवश्यकता है।सी #

Every Day 
Every Week 
Every 2 Weeks 
Every 3 Weeks 
Every Month 
Every 2 Months 
... 

यह करने के लिए सही तरीका क्या है: शुरुआत में मैं सिर्फ एक शुरुआत दिनांक/समय और जानकारी कैसे इस घटना को दोहराना चाहिए? यह अलग-अलग समय क्षेत्रों और दिन की बचत समय सेटिंग के साथ सही ढंग से काम करना चाहिए। मुझे लगता है कि मुझे स्थानीय डेटटाइम में केवल दिन/सप्ताह/महीने जोड़ना चाहिए और फिर इसे यूटीसी में परिवर्तित करना चाहिए। लेकिन मुझे इसके बारे में निश्चित नहीं है। क्या होता है यदि मैं कुछ दिन जोड़ता हूं और यह वह समय होगा जब हमें अपने घड़ियों को एक घंटे आगे समायोजित करने की आवश्यकता होगी। इस मामले में इस बार मौजूद नहीं होगा।

नीचे कोड मैंने लिखा है, लेकिन मुझे यकीन है कि यह हर मामले में सही ढंग से काम करता है नहीं कर रहा हूँ:

private static List<DateTime> FindOccurrences(DateTime localStart, Repeat repeat, int occurrences) 
{ 
    var result = new List<DateTime> { localStart }; 
    switch (repeat) 
    { 
     case Repeat.Daily: 
      for (int i = 1; i <= occurrences; i++) 
       result.Add(localStart.AddDays(i)); 
      break; 
     case Repeat.Every2Weeks: 
      for (int i = 1; i <= occurrences; i++) 
       result.Add(localStart.AddDays((7 * 2) * i)); 
      break; 
     ... 
    } 
    return result; 
} 

public List<Event> CreateRepeating(string timeZone, Repeat repeat, int repeatEnds, DateTime localStart, int eventDuration) 
{ 
    var events = new List<Event>(); 
    var occurrences = FindOccurrences(localStart, repeat, repeatEnds); 
    foreach (var occurrence in occurrences) 
    { 
     var item = new Event(); 
     item.Start = occurrence.ToUtcTime(timeZone); 
     item.End = occurrence.ToUtcTime(timeZone).AddMinutes(eventDuration); 
     events.Add(item); 
    } 
    return events; 
} 

पुनश्च: सभी तिथियों डेटाबेस में UTC स्वरूप में संग्रहीत हैं।

+2

[नोडटाइम] (http://code.google.com/p/noda-time/) पर एक नज़र डालें - इसने दिनांक और समय क्षेत्र में निहित कई चुनौतियों को माना है। – StuartLC

उत्तर

5

आंशिक उत्तर। मैं नहीं बल्कि करने के लिए

public enum TimePeriod { 
    None = 0, 
    Day = 1, 
    // Just week, no "two weeks, three weeks etc." 
    Week = 2, 
    Month = 3 
    } 

    public static class Occurrencies { 
    // May be you want to convert it to method extension: "this DateTime from" 
    public static IEnumerable<DateTime> FindInterval(DateTime from, 
                TimePeriod period, 
                int count) { 
     while (true) { 
     switch (period) { 
      case TimePeriod.Day: 
      from = from.AddDays(count); 

      break; 
      case TimePeriod.Week: 
      from = from.AddDays(7 * count);  

      break; 
      case TimePeriod.Month: 
      from = from.AddMonths(count);  

      break; 
     } 

     yield return from; 
     } 
    } 
    } 

उपयोग कार्यान्वयन को बदल देंगे:

// Get 5 2-week intervals 
    List<DateTime> intervals2Weeks = Occurrencies 
    .FindInterval(DateTime.Now, TimePeriod.Week, 2) 
    .Take(5) 
    .ToList(); 

    // Get 11 3-month intervals 
    List<DateTime> intervals3Months = Occurrencies 
    .FindInterval(DateTime.Now, TimePeriod.Month, 3) 
    .Take(11) 
    .ToList(); 
8

निर्धारण या भविष्य की घटनाओं, विशेष रूप से आवर्ती ईवेंट की तिथियां गणना करते समय, एक बहुत जटिल विषय है। मैंने इसके बारे में कुछ बार लिखा है, हालांकि अन्य भाषाओं के परिप्रेक्ष्य से (देखें: 1, 2, 3, 4)।

मुझे डर है कि यह आपको चलाने के लिए सही कोड देने के लिए एक विषय का बहुत व्यापक है। विवरण आपके आवेदन के लिए बहुत विशिष्ट होंगे। लेकिन यहां कुछ सुझाव दिए गए हैं।

सामान्य में:

  • यूटीसी उपयोग केवल समय है कि घटना का एक उदाहरण होने के लिए है में पेश पल के लिए।

  • स्थानीय समय में वास्तविक घटना को स्टोर करें। समय क्षेत्र आईडी भी स्टोर करें।

  • Do नहीं दुकान समय क्षेत्र ऑफसेट। यह प्रत्येक घटना के लिए व्यक्तिगत रूप से देखा जाना चाहिए।

  • घटना यूटीसी के रूप में घटना की आगामी घटना (ओं) परियोजना है ताकि आप जानते हों कि घटना के आधार पर कोई कार्रवाई कैसे करें (या जो भी आपके परिदृश्य के लिए समझ में आता है)।

  • तय करें कि डेलाइट सेविंग टाइम के लिए क्या करना है, जब कोई घटना वसंत-आगे के अंतर में पड़ती है, या फॉल-बैक ओवरलैप होती है। आपकी ज़रूरतें अलग-अलग हो सकती हैं, लेकिन एक सामान्य रणनीति वसंत अंतर के आगे बढ़ें, और पहले गिरावट में घटना का चयन करें। यदि आप सुनिश्चित नहीं हैं कि मेरा क्या मतलब है, तो the dst tag wiki देखें।

  • ध्यान दें कि एक महीने के अंत में तारीखों को कैसे संभालना है, इस बारे में सावधानी से सोचें। सभी महीनों में समान संख्या में दिन नहीं होते हैं, और कैलेंडर गणित मुश्किल है। dt.AddMonths(1).AddMonths(1) आवश्यक नहीं है dt.AddMonths(2) के समान।

  • समय क्षेत्र डेटा अपडेट के शीर्ष पर बने रहें। कोई भी भविष्य की भविष्यवाणी नहीं कर सकता, और दुनिया की सरकारें चीजों को बदलना पसंद करती हैं!

  • आपको शेड्यूल के मूल स्थानीय समय मानों को बनाए रखने की आवश्यकता है, ताकि आप घटनाओं के यूटीसी मूल्यों को फिर से प्रोजेक्ट कर सकें। आपको इसे समय-समय पर करना चाहिए, या जब भी आप एक समय क्षेत्र अपडेट लागू करते हैं (यदि आप उन्हें मैन्युअल रूप से ट्रैक कर रहे हैं)। The timezone tag wiki में विभिन्न समय क्षेत्र डेटाबेस और वे कैसे अपडेट किए गए हैं के बारे में विवरण है।

  • Noda Time और IANA/TZDB समय क्षेत्रों के उपयोग पर विचार। माइक्रोसॉफ्ट द्वारा प्रदान किए गए प्रकार के प्रकार और समय क्षेत्र की तुलना में वे इस प्रकार के काम के लिए अधिक उपयुक्त हैं।

  • स्थानीय समय क्षेत्र का उपयोग करने से बचने के लिए सावधान रहें। आपके पास DateTime.Now, ToLocalTime, या ToUniversalTime पर कोई कॉल नहीं होना चाहिए। याद रखें, स्थानीय समय क्षेत्र मशीन पर आधारित है जहां कोड चल रहा है, और इससे आपके कोड के व्यवहार को प्रभावित नहीं करना चाहिए। The Case Against DateTime.Now में और पढ़ें।

  • तुम सिर्फ एक अनुसूचित काम शुरू करने के लिए यह सब कर रहे हैं, तो आप शायद एक पूर्व डिब्बाबंद समाधान पर एक नज़र, इस तरह के Quartz.NET के रूप में लेना चाहिए। यह मुफ़्त, खुला स्रोत, अत्यधिक कार्यात्मक है, और इसमें कई किनारे के मामलों को शामिल किया गया है जिनके बारे में आपने सोचा नहीं होगा।