.NET

2012-11-11 33 views
6

में डीएसटी समय के दौरान यूटीसी ऑफसेट कैसे प्राप्त करें I अंतराल में, एक टाइमज़ोन में देखे गए सभी ऑफ़सेट प्राप्त करने का प्रयास कर रहा हूं। नीचे वह कार्य है जिसे मैंने पूरा करने के लिए उपयोग किया था, मुझे पता है कि आप मानक समय के दौरान टाइमज़ोन के लिए UTC offset प्राप्त करने के लिए TimeZoneInfo.BaseUtcOffset का उपयोग कर सकते हैं, लेकिन डेलाइट सेविंग टाइम के दौरान एक प्राप्त करने के लिए कोई समान तरीका नहीं है जब तक आप कोई विशेष DST समय नहीं देते GetUTCOffset() विधि के लिए।.NET

static void GetOffsets(DateTime startTime, DateTime endTime, TimeZoneInfo tz) 
{ 
    var result = new HashSet<int>(); 
    var adjRules = tz.GetAdjustmentRules(); 
    result.Add(tz.BaseUtcOffset); 

    foreach (var adjustmentRule in adjRules) 
    { 
     if ((startTime >= adjustmentRule.DateStart && startTime <= adjustmentRule.DateEnd) || (endTime >= adjustmentRule.DateStart && endTime <= adjustmentRule.DateEnd) || 
      (stTime <= adjustmentRule.DateStart && endTime >= adjustmentRule.DateEnd)) 
     { 
      if(adjustmentRule.DaylightDelta != TimeSpan.Zero) 
      { 
       if (!result.Contains(tz.BaseUtcOffset + adjustmentRule.DaylightDelta)) 
         result.Add((tz.BaseUtcOffset + adjustmentRule.DaylightDelta)); 
      } 
     } 
    } 

    foreach (var res in result) 
    { 
     Console.WriteLine(res); 
    } 
} 

कृपया मुझे बताएं कि ऐसा करने का एक बेहतर तरीका है या नहीं।

+0

कोड रहस्यमय है। यदि आप सभी संभावित ऑफसेट चाहते हैं तो स्टार्टटाइम और एंडटाइम पर परीक्षणों को हटा दें। परिणाम कैसे उपयोगी हो सकता है देखना मुश्किल है। –

+0

हाय हंस, इस तथ्य को ध्यान में रखते हुए कि माइक्रोसॉफ्ट के नियम हैं जो डेलाइटडेल्टा को निर्धारित करते हैं, मैंने माना कि इस विधि के लिए सामान्य होने के लिए मुझे अंतराल पर विचार करना था या डेटटाइम का उपयोग करना था। मिनट और डेटटाइम। सभी पिछली ऑफसेट्स को देखने के लिए अंतराल के रूप में मैक्स। – vinasi

+0

उपयोग केस: मैं इस ऑफसेट जानकारी का उपयोग एक एसक्यूएल सर्वर डीबी संग्रहीत प्रक्रिया को पास करने के लिए करता हूं, यूआई जो एक रिपोर्ट चलाती है, में एक ड्रॉपडाउन होता है जो सभी 24 "1 घंटा: एक दिन में टाइमइंटरवल्स (पूर्व 1 पीएम -2 पीएम) सूचीबद्ध करता है, मैं इसे परिवर्तित करता हूं यूटीसी में डेटटाइम सहेजे गए एक संग्रहीत प्रोसेस को पास करने के लिए ऑफसेट। अगर इस उपयोग के मामले में नहीं है, तो भी मैं यह जानने की कोशिश कर रहा हूं कि मेरे मूल प्रश्न को हल करने का कोई अन्य तरीका है या नहीं। – vinasi

उत्तर

-1

यदि आप तिथियों के साथ कुछ भी जटिल कर रहे हैं तो आपको Noda Time (जो जोडा टाइम जावा लाइब्रेरी का बंदरगाह है) पर एक नज़र डालना चाहिए। कांटेदार समय क्षेत्र के मुद्दों से निपटने के लिए इसका पूरा नामस्थान है।

0

मैं एक निर्दिष्ट टाइमज़ोनिन्फो के लिए एक वर्ष अंतराल के भीतर ऑफसेट को यूटीसी अंतराल के लिए विचार करने की आवश्यकता के लिए इस विधि के साथ आया था। मैं इस संग्रह को यूटीसी में अंतराल फ़िल्टर इनपुट ("1am - 2am") के लिए सहेजे गए डेटाटाइम फ़ील्ड को फ़िल्टर करने के लिए डेटाबेस में पास करता हूं, मैंने अपने सिस्टम में सभी टाइमज़ोन के लिए इसका परीक्षण किया और यह ठीक काम किया। हालांकि यह मेरे मूल प्रश्न का उत्तर नहीं है क्योंकि मैं अभी भी ऑफसेट प्राप्त करने के लिए समायोजन नियमों का उपयोग कर रहा हूं, मैंने इस बार इसे प्रयोग करने योग्य बनाने की कोशिश की।

class Program 
{ 
    static void Main(string[] args) 
    { 
     foreach (var tz in TimeZoneInfo.GetSystemTimeZones()) 
     { 
      var result = GetUTCOffsetsByUTCIntervals(1900, 2012, tz); 
      Console.WriteLine(tz.DisplayName); 
      foreach (var tuple in result) 
      { 
       Console.WriteLine(tuple.Item1 + "  " + tuple.Item2 + " " + tuple.Item3); 
      } 
      Console.WriteLine("------------------------------------------------------------"); 
     } 
     Console.Read(); 
    } 

    public static List<Tuple<TimeSpan, DateTime, DateTime>> GetUTCOffsetsByUTCIntervals(int stYear, int endYear, TimeZoneInfo tz) 
    { 
     var cal = CultureInfo.CurrentCulture.Calendar; 
     var offsetsByUTCIntervals = new List<Tuple<TimeSpan, DateTime, DateTime>>(); 
     var adjRules = tz.GetAdjustmentRules(); 
     for (var year = stYear; year <= endYear && year < DateTime.MaxValue.Year && year >= DateTime.MinValue.Year; year++) 
     { 
      var adjRule = 
       adjRules.FirstOrDefault(
        rule => 
        rule.DateStart.Year == year || rule.DateEnd.Year == year || 
        (rule.DateStart.Year < year && rule.DateEnd.Year > year)); 

      var yrStTime = new DateTime(year, 1, 1); 
      var yrEndTime = yrStTime.AddYears(1).AddTicks(-1); 

      if (adjRule != null) 
      { 
       var tStDate = GetTransitionDate(adjRule.DaylightTransitionStart, year); 
       var tEnddate = GetTransitionDate(adjRule.DaylightTransitionEnd, year); 

       var stTsp = adjRule.DaylightTransitionStart.TimeOfDay.TimeOfDay; 

       var endTsp = adjRule.DaylightTransitionEnd.TimeOfDay.TimeOfDay; 

       if (yrStTime.Date == tStDate && yrStTime.TimeOfDay == stTsp) 
        yrStTime = yrStTime.Add(adjRule.DaylightDelta); 

       if (yrEndTime.Date == tEnddate && yrEndTime.TimeOfDay == endTsp) 
        yrEndTime = yrEndTime.Subtract(adjRule.DaylightDelta); 

       if (tStDate.Month > tEnddate.Month) 
       { 
        offsetsByUTCIntervals.Add(new Tuple<TimeSpan, DateTime, DateTime>(tz.BaseUtcOffset + adjRule.DaylightDelta, ConvertTimeToUtc(yrStTime, tz), ConvertTimeToUtc(tEnddate.AddTicks(endTsp.Ticks - 1), tz))); 
        offsetsByUTCIntervals.Add(new Tuple<TimeSpan, DateTime, DateTime>(tz.BaseUtcOffset, ConvertTimeToUtc(tEnddate.Add(endTsp.Subtract(adjRule.DaylightDelta)), tz), ConvertTimeToUtc(tStDate.AddTicks(stTsp.Ticks - 1), tz))); 
        offsetsByUTCIntervals.Add(new Tuple<TimeSpan, DateTime, DateTime>(tz.BaseUtcOffset + adjRule.DaylightDelta, ConvertTimeToUtc(tStDate.Add(stTsp.Add(adjRule.DaylightDelta)), tz), ConvertTimeToUtc(yrEndTime, tz))); 
       } 
       else 
       { 
        offsetsByUTCIntervals.Add(new Tuple<TimeSpan, DateTime, DateTime>(tz.BaseUtcOffset, ConvertTimeToUtc(yrStTime, tz), ConvertTimeToUtc(tStDate.AddTicks(stTsp.Ticks - 1), tz))); 
        offsetsByUTCIntervals.Add(new Tuple<TimeSpan, DateTime, DateTime>(tz.BaseUtcOffset + adjRule.DaylightDelta, ConvertTimeToUtc(tStDate.Add(stTsp.Add(adjRule.DaylightDelta)), tz), ConvertTimeToUtc(tEnddate.AddTicks(endTsp.Ticks - 1), tz))); 
        offsetsByUTCIntervals.Add(new Tuple<TimeSpan, DateTime, DateTime>(tz.BaseUtcOffset, ConvertTimeToUtc(tEnddate.Add(endTsp.Subtract(adjRule.DaylightDelta)), tz), ConvertTimeToUtc(yrEndTime, tz))); 
       } 
      } 
      else 
      { 
       offsetsByUTCIntervals.Add(new Tuple<TimeSpan, DateTime, DateTime>(tz.BaseUtcOffset, ConvertTimeToUtc(yrStTime, tz), ConvertTimeToUtc(yrEndTime, tz))); 
      } 
     } 
     return offsetsByUTCIntervals; 
    } 

    public static DateTime ConvertTimeToUtc(DateTime date, TimeZoneInfo timeZone) 
    { 
     if (date == null || timeZone == null) 
     { 
      return date; 
     } 
     DateTime convertedDate = TimeZoneInfo.ConvertTimeToUtc(date, timeZone); 
     return convertedDate; 
    } 

    //copy from msdn http://msdn.microsoft.com/en-us/library/system.timezoneinfo.transitiontime.isfixeddaterule.aspx 
    private static DateTime GetTransitionDate(TimeZoneInfo.TransitionTime transition, int year) 
    { 
     if (transition.IsFixedDateRule) 
      return new DateTime(year, transition.Month, transition.Day); 

     int transitionDay; 
     var cal = CultureInfo.CurrentCulture.Calendar; 
     var startOfWeek = transition.Week * 7 - 6; 
     var firstDayOfWeek = (int)cal.GetDayOfWeek(new DateTime(year, transition.Month, 1)); 
     var changeDayOfWeek = (int)transition.DayOfWeek; 

     if (firstDayOfWeek <= changeDayOfWeek) 
      transitionDay = startOfWeek + (changeDayOfWeek - firstDayOfWeek); 
     else 
      transitionDay = startOfWeek + (7 - firstDayOfWeek + changeDayOfWeek); 

     if (transitionDay > cal.GetDaysInMonth(year, transition.Month)) 
      transitionDay -= 7; 
     return new DateTime(year, transition.Month, transitionDay); 
    } 

    /* static void GetOffsets(DateTime startTime, DateTime endTime, TimeZoneInfo tz) 
    { 
     var result = new HashSet<string>(); 
     var adjRules = tz.GetAdjustmentRules(); 
     result.Add(tz.BaseUtcOffset.ToString()); 

     foreach (var adjustmentRule in adjRules) 
     { 
      if ((startTime >= adjustmentRule.DateStart && startTime <= adjustmentRule.DateEnd) 
        || (endTime >= adjustmentRule.DateStart && endTime <= adjustmentRule.DateEnd) 
       || (startTime <= adjustmentRule.DateStart && endTime >= adjustmentRule.DateEnd)) 
      { 
       if(adjustmentRule.DaylightDelta != TimeSpan.Zero) 
       { 
        if (!result.Contains((tz.BaseUtcOffset + adjustmentRule.DaylightDelta).ToString())) 
         result.Add((tz.BaseUtcOffset + adjustmentRule.DaylightDelta).ToString()); 
       } 
      } 
     } 
     Console.Write(tz.DisplayName + " "); 
     foreach (var res in result) 
     { 
      Console.Write(res); 
     } 
    }*/ 
} 
5

मैं एक अंतराल में, सभी ऑफसेट एक समय क्षेत्र में देखा प्राप्त करने की कोशिश कर रहा हूँ।

मैं दृढ़ता से सलाह आप सीधे TimeZoneInfo उपयोग करने के लिए कोशिश कर रहा से बचने के लिए होगा। समायोजन नियम कुछ वर्षों में कुछ क्षेत्रों के लिए आश्चर्यजनक रूप से अजीब हो सकते हैं, जैसा कि मैंने अपने खर्च में पाया है।

जबकि मैं पक्षपातपूर्ण हूं, मैं Noda Time का उपयोग करने का सुझाव दूंगा, जो TimeZoneInfo को लपेट सकता है और BclDateTimeZone.FromTimeZoneInfo के माध्यम से आपके लिए कड़ी मेहनत कर सकता है। आपका प्रश्न आवश्यकताओं के संदर्भ में पूरी तरह स्पष्ट नहीं है, लेकिन यदि आप जो करने की कोशिश कर रहे हैं उसके बारे में कुछ और कह सकते हैं, तो मैं आपके लिए उपयुक्त नोडा टाइम कोड लिख सकता हूं।

आपका प्रारंभिक वर्णन कुछ इस तरह से लागू किया जा सकता:

public IEnumerable<ZoneInterval> GetZoneIntervalsInInterval 
    (this DateTimeZone zone, Interval interval) 
{ 
    Instant current = interval.Start; 
    while (current < interval.End && current != Instant.MaxValue) 
    { 
     ZoneInterval zi = zone.GetZoneInterval(current); 
     yield return zi; 
     current = zi.End; 
    } 
} 
फिर

:

var zone = BclDateTimeZone.FromTimeZoneInfo(tzInfo); 
var offsets = zone.GetZoneIntervalsInInterval(interval) 
        .Select(zi => zi.WallOffset) 
        .Distinct(); 

संभालने है कि आपके द्वारा एक ही बात मतलब है "ऑफसेट" के रूप में मैं कर (अर्थात् अंतर यूटीसी और स्थानीय समय के बीच)।

+0

मदद के लिए धन्यवाद! @Jon। दुर्भाग्य से मेरे पास परियोजना के इस चरण में तीसरे पक्ष के पुस्तकालयों को जोड़ने की विलासिता नहीं है, जबकि हम देव रिलीज से 3 सप्ताह दूर हैं, मुझे अब के लिए .NET बीसीएल विधियों पर भरोसा करना है, जैसा कि मैंने अपने प्रश्न में उल्लेख किया है, मेरी आवश्यकता है ऐतिहासिक डेटा फ़िल्टर करने के लिए जहां डेटाटाइम एसटीएल सर्वर में यूटीसी में हैं, जैसे '8am -9am' जैसे समय फ़िल्टर। मूल रूप से रूपांतरण के लिए उपयोग किए जाने वाले टाइमज़ोन को कॉन्फ़िगरेशन में प्रदान किया जाता है, इसलिए टाइमज़ोन दिया गया है, मुझे ऑफसेट्स को यह पता होना चाहिए कि मैंने देखा है ताकि मैं डेटाबेस में ऐतिहासिक डेटा फ़िल्टर करने के लिए इस जानकारी का उपयोग कर सकूं। – vinasi

+0

मैं इसे "उत्तर" में अपनी पोस्ट के साथ काम करने में सक्षम था, कम से कम यह ब्याज (ईएसटी, सीएसटी, पीएसटी, जीबीटी) के मौजूदा कामों के लिए काम कर रहा है, आपने उल्लेख किया है कि समायोजन नियम कुछ वर्षों में कुछ क्षेत्रों के लिए अजीब हैं। आपको लगता है कि टाइमज़ोनिन्फो की जानकारी अजीब थी, जब आप सोचते हैं तो आपका रैपर भरोसा करता है? – vinasi