Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

c#

datetime

dst

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 "as of" time in that time zone. The time returned should be in the provided time zone. The function I want has this signature:

public DateTime GetNextTransition(DateTime asOfTime, TimeZoneInfo timeZone)
{
    // Implement me!
}

For example, if I pass in the "Eastern Standard Time" TimeZoneInfo object, and 1/21/2011@17:00 as the "asOfTime", I expect this function to return 3/13/2011@2:00.

The System.TimeZoneInfo.TransitionTime structure appears to have all the information I need, but ideally there would be some sort of built-in mechanism to convert the rule into an actual date. Anyone have any suggestions?

like image 465
Stuart Lange Avatar asked Jan 21 '11 23:01

Stuart Lange


People also ask

What happens when we switch to daylight Savings time?

When Daylight Saving Time (DST) begins, we lose an hour. When it ends, we gain an hour. So how exactly does the DST switch work? When Daylight Saving Time starts in the spring, we lose an hour of sleep.

How do you transition time change?

Easing into the time change is the best way to make the transition smooth. We suggest starting the transition as early as a week before the time change. Small adjustments, just 10 or 15 minutes a day, can help to move awake and bedtimes slowly.

What hour repeats during daylight savings?

When in the morning? In the U.S., clocks change at 2:00 a.m. local time. In spring, clocks spring forward from 1:59 a.m. to 3:00 a.m.; in fall, clocks fall back from 1:59 a.m. to 1:00 a.m. In the EU, clocks change at 1:00 a.m. Universal Time.

What do you call the time after daylight Savings?

Standard time is the local time in a country or region when Daylight Saving Time (DST) is not in use. Standard time is also known as winter time or normal time. ©iStockphoto.com/JaysonPhotography.


2 Answers

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

MSDN - TransitionTime

like image 150
jamiegs Avatar answered Sep 22 '22 00:09

jamiegs


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.

like image 23
codtex Avatar answered Sep 21 '22 00:09

codtex