Get the next date/time at which a daylight savings time transition occurs

后端 未结 3 949
孤街浪徒
孤街浪徒 2021-01-17 14:46

I would like to write (or use if it already exits) a function in C# that returns the date/time of the next DST transition given a System.TimeZoneInfo object and a particular

相关标签:
3条回答
  • 2021-01-17 15:17

    Take a look at the example on this page, I think it'll get what you need.

    MSDN - TransitionTime

    0 讨论(0)
  • 2021-01-17 15:24

    System.TimeZoneInfo.TransitionTime looks like a structure that can hold such time transition data, not a function that figures out the actual values. To create such a function, I would find the data online somewhere, then create values using the static CreateFloatingDateRule or CreateFixedDateRule methods.

    0 讨论(0)
  • 2021-01-17 15:26

    Hello_ there. It might be too late but I will post here the code that I used for this purpose. This could possibly safe someone's time to implement it. I did it actually with the help of the link is @Jamiegs answer.

        public static DateTime? GetNextTransition(DateTime asOfTime, TimeZoneInfo timeZone)
        {
            TimeZoneInfo.AdjustmentRule[] adjustments = timeZone.GetAdjustmentRules();
            if (adjustments.Length == 0)
            {
                // if no adjustment then no transition date exists
                return null;
            }
    
            int year = asOfTime.Year;
            TimeZoneInfo.AdjustmentRule adjustment = null;
            foreach (TimeZoneInfo.AdjustmentRule adj in adjustments)
            {
                // Determine if this adjustment rule covers year desired
                if (adj.DateStart.Year <= year && adj.DateEnd.Year >= year)
                {
                    adjustment = adj;
                    break;
                }
            }
    
            if (adjustment == null)
            {
                // no adjustment found so no transition date exists in the range
                return null;
            }
    
    
            DateTime dtAdjustmentStart = GetAdjustmentDate(adjustment.DaylightTransitionStart, year);
            DateTime dtAdjustmentEnd = GetAdjustmentDate(adjustment.DaylightTransitionEnd, year);
    
    
            if (dtAdjustmentStart >= asOfTime)
            {
                // if adjusment start date is greater than asOfTime date then this should be the next transition date
                return dtAdjustmentStart;
            }
            else if (dtAdjustmentEnd >= asOfTime)
            {
                // otherwise adjustment end date should be the next transition date
                return dtAdjustmentEnd;
            }
            else
            {
                // then it should be the next year's DaylightTransitionStart
    
                year++;
                foreach (TimeZoneInfo.AdjustmentRule adj in adjustments)
                {
                    // Determine if this adjustment rule covers year desired
                    if (adj.DateStart.Year <= year && adj.DateEnd.Year >= year)
                    {
                        adjustment = adj;
                        break;
                    }
                }
    
                dtAdjustmentStart = GetAdjustmentDate(adjustment.DaylightTransitionStart, year);
                return dtAdjustmentStart;
            }
        }
    
    
        public static DateTime GetAdjustmentDate(TimeZoneInfo.TransitionTime transitionTime, int year)
        {
            if (transitionTime.IsFixedDateRule)
            {
                return new DateTime(year, transitionTime.Month, transitionTime.Day);
            }
            else
            {
                // For non-fixed date rules, get local calendar
                Calendar cal = CultureInfo.CurrentCulture.Calendar;
                // Get first day of week for transition
                // For example, the 3rd week starts no earlier than the 15th of the month
                int startOfWeek = transitionTime.Week * 7 - 6;
                // What day of the week does the month start on?
                int firstDayOfWeek = (int)cal.GetDayOfWeek(new DateTime(year, transitionTime.Month, 1));
                // Determine how much start date has to be adjusted
                int transitionDay;
                int changeDayOfWeek = (int)transitionTime.DayOfWeek;
    
                if (firstDayOfWeek <= changeDayOfWeek)
                    transitionDay = startOfWeek + (changeDayOfWeek - firstDayOfWeek);
                else
                    transitionDay = startOfWeek + (7 - firstDayOfWeek + changeDayOfWeek);
    
                // Adjust for months with no fifth week
                if (transitionDay > cal.GetDaysInMonth(year, transitionTime.Month))
                    transitionDay -= 7;
    
                return new DateTime(year, transitionTime.Month, transitionDay, transitionTime.TimeOfDay.Hour, transitionTime.TimeOfDay.Minute, transitionTime.TimeOfDay.Second);
            }
        }
    

    Sample usage will look like this:

    // This should give you DateTime object for date 26 March 2017 
    // because this date is first transition date after 1 January 2017 for Central Europe Standard Time zone
    DateTime nextTransitionDate = GetNextTransition(new DateTime(2017, 1, 1), TimeZoneInfo.FindSystemTimeZoneById("Central Europe Standard Time"))
    

    You can find the code that I played with here.

    0 讨论(0)
提交回复
热议问题