Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

.NET TimeZone.CurrentTimeZone.GetDaylightChanges returns wrong DST for 2005

I used the following code to display the Daylight Saving Time for the years between 2005 and 2035.

For the year 2005, this page shows the DST is between April 3rd and October 30th. But the GetDaylightChanges returns March 13 and November 6th.

Is the .NET GetDaylightChanges a reliable function?

enter image description here

    public static void GetCurrentTimeZone()
    {
        for (int i = 0; i < 30; i++)
        {
            var dlt = TimeZone.CurrentTimeZone.GetDaylightChanges(2005 + i);

            Console.WriteLine(2005 + i);
            Console.WriteLine(dlt.Start.ToLongDateString());
            Console.WriteLine(dlt.End.ToLongDateString());

            Console.WriteLine(" ");
        }
    }
like image 429
wonderful world Avatar asked Mar 17 '23 05:03

wonderful world


1 Answers

From 1987-2006, the rule was: DST is in effect from the first Sunday in April through the last Sunday in October.

From 2007-present, the rule was: DST is in effect from the second Sunday in March through the first Sunday in November.

However, as pointed out by @MaheshKava, the remarks section of the GetDaylightChanges API says this:

Because the TimeZone class supports only one daylight saving time adjustment rule, the GetDaylightChanges method applies the current adjustment rule to any year, regardless of whether the adjustment rule actually applies to that year.

This means that the current rule (2nd Sunday in March through the 1st Sunday in November) is being applied for all years regardless of whether this rule was actually in effect during that year. So, to summarize, GetDaylightChanges will give you inaccurate results for any year prior to 2007, and apparently this is by design.

The API documentation goes on further to say that you can use TimeZoneInfo.GetAdjustmentRules to get more accurate information. I was curious about this, so I wrote this code:

    static void Main(string[] args)
    {
        PrintAllDaylightSavingsAdjustmentDates();
        Console.ReadLine();
    }

    public static void PrintAllDaylightSavingsAdjustmentDates()
    {
        TimeZoneInfo timeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById("Pacific Standard Time");
        TimeZoneInfo.AdjustmentRule[] adjustmentRules = timeZoneInfo.GetAdjustmentRules();

        for (int year = 2000; year < 2030; year++)
        {
            PrintDaylightSavingsAdjustmentDatesForYear(adjustmentRules, year);
        }
    }

    public static void PrintDaylightSavingsAdjustmentDatesForYear
        (
        TimeZoneInfo.AdjustmentRule[] adjustmentRules, 
        int year
        )
    {
        DateTime firstOfYear = new DateTime(year, 1, 1);

        foreach (TimeZoneInfo.AdjustmentRule adjustmentRule in adjustmentRules)
        {
            if ((adjustmentRule.DateStart <= firstOfYear) && (firstOfYear <= adjustmentRule.DateEnd))
            {
                Console.WriteLine("In {0}, DST started on {1} and ended on {2}.",
                    year,
                    GetTransitionDate(adjustmentRule.DaylightTransitionStart, year).ToString("MMMM dd"),
                    GetTransitionDate(adjustmentRule.DaylightTransitionEnd, year).ToString("MMMM dd"));
            }
        }
    }

    public static DateTime GetTransitionDate
        (
        TimeZoneInfo.TransitionTime transitionTime,
        int year
        )
    {
        if (transitionTime.IsFixedDateRule)
        {
            return new DateTime(year, transitionTime.Month, transitionTime.Day);
        }
        else
        {
            if (transitionTime.Week == 5)
            {
                // Special value meaning the last DayOfWeek (e.g., Sunday) in the month.
                DateTime transitionDate = new DateTime(year, transitionTime.Month, 1);
                transitionDate = transitionDate.AddMonths(1);

                transitionDate = transitionDate.AddDays(-1);
                while (transitionDate.DayOfWeek != transitionTime.DayOfWeek)
                {
                    transitionDate = transitionDate.AddDays(-1);
                }

                return transitionDate;
            }
            else
            {
                DateTime transitionDate = new DateTime(year, transitionTime.Month, 1);
                transitionDate = transitionDate.AddDays(-1);

                for (int howManyWeeks = 0; howManyWeeks < transitionTime.Week; howManyWeeks++)
                {
                    transitionDate = transitionDate.AddDays(1);
                    while (transitionDate.DayOfWeek != transitionTime.DayOfWeek)
                    {
                        transitionDate = transitionDate.AddDays(1);
                    }
                }

                return transitionDate;
            }
        }
    }

Which spits out the following output:

In 2000, DST started on April 02 and ended on October 29.
In 2001, DST started on April 01 and ended on October 28.
In 2002, DST started on April 07 and ended on October 27.
In 2003, DST started on April 06 and ended on October 26.
In 2004, DST started on April 04 and ended on October 31.
In 2005, DST started on April 03 and ended on October 30.
In 2006, DST started on April 02 and ended on October 29.
In 2007, DST started on March 11 and ended on November 04.
In 2008, DST started on March 09 and ended on November 02.
In 2009, DST started on March 08 and ended on November 01.
In 2010, DST started on March 14 and ended on November 07.
In 2011, DST started on March 13 and ended on November 06.
In 2012, DST started on March 11 and ended on November 04.
In 2013, DST started on March 10 and ended on November 03.
In 2014, DST started on March 09 and ended on November 02.
In 2015, DST started on March 08 and ended on November 01.
In 2016, DST started on March 13 and ended on November 06.
In 2017, DST started on March 12 and ended on November 05.
In 2018, DST started on March 11 and ended on November 04.
In 2019, DST started on March 10 and ended on November 03.
In 2020, DST started on March 08 and ended on November 01.
In 2021, DST started on March 14 and ended on November 07.
In 2022, DST started on March 13 and ended on November 06.
In 2023, DST started on March 12 and ended on November 05.
In 2024, DST started on March 10 and ended on November 03.
In 2025, DST started on March 09 and ended on November 02.
In 2026, DST started on March 08 and ended on November 01.
In 2027, DST started on March 14 and ended on November 07.
In 2028, DST started on March 12 and ended on November 05.
In 2029, DST started on March 11 and ended on November 04.
like image 132
Rajeev Goel Avatar answered Apr 05 '23 22:04

Rajeev Goel