Bug 26008 - Wrong DST when TimeZoneInfo has floating date rules.
Summary: Wrong DST when TimeZoneInfo has floating date rules.
Alias: None
Product: Class Libraries
Classification: Mono
Component: System.Core (show other bugs)
Version: unspecified
Hardware: PC Mac OS
: --- normal
Target Milestone: Untriaged
Assignee: marcos.henrich
Depends on:
Reported: 2015-01-14 06:22 UTC by marcos.henrich
Modified: 2015-01-15 06:45 UTC (History)
1 user (show)

Is this bug a regression?: ---
Last known good build:

Notice (2018-05-24): bugzilla.xamarin.com is now in read-only mode.

Please join us on Visual Studio Developer Community and in the Xamarin and Mono organizations on GitHub to continue tracking issues. Bugzilla will remain available for reference in read-only mode. We will continue to work on open Bugzilla bugs, copy them to the new locations as needed for follow-up, and add the new items under Related Links.

Our sincere thanks to everyone who has contributed on this bug tracker over the years. Thanks also for your understanding as we make these adjustments and improvements for the future.

Please create a new report on GitHub or Developer Community with your current version information, steps to reproduce, and relevant error messages or log files if you are hitting an issue that looks similar to this resolved bug and you do not yet see a matching new report.

Related Links:

Description marcos.henrich 2015-01-14 06:22:44 UTC
The following bug, test case and possible fix has been reported by nachocove.com

The Mono runtime has a bug in how it calculates the daylight saving transition dates when the time zone uses a floating rule (e.g. 2nd Sunday of the month).  In some cases, the transition to or from daylight saving time will happen a week earlier than it is supposed to.

Here is a function that will check for the presence of the bug.  It creates a custom time zone where daylight saving time starts on the 2nd Sunday in March, and then checks whether Friday, March 7, 2014 (which is in between the first and second Sundays) is reported as being daylight saving time.

        /// <summary>
        /// Mono has a bug in its daylight saving code, where a transition to or from
        /// daylight saving time might happen a week early.  This function tests whether
        /// or not the runtime in use has this particular bug.
        /// </summary>
        /// <returns><c>true</c>, if the runtime is correct, <c>false</c> if the runtime has the bug.</returns>
        /// <remarks>
        /// The bug happens when (1) the transition is a floating rule rather than a
        /// fixed rule, (2) the transition happens in a week other than the first week,
        /// and (3) the day of the week of the first day of the month is later in the
        /// week than the day of the week that the transition happens on.  (Since most
        /// transitions happen on Sundays, which is the first day of the week, condition
        /// #3 almost always applies.)
        /// </remarks>
        private static bool DaylightSavingCorrectnessCheck ()
            // Construct a custom time zone where daylight saving time starts on the
            // 2nd Sunday in March.
            var transitionToDaylight = TimeZoneInfo.TransitionTime.CreateFloatingDateRule (
                new DateTime (1, 1, 1, 2, 0, 0), 3, 2, DayOfWeek.Sunday);
            var transitionToStandard = TimeZoneInfo.TransitionTime.CreateFloatingDateRule (
                new DateTime (1, 1, 1, 2, 0, 0), 11, 1, DayOfWeek.Sunday);
            var adjustment = TimeZoneInfo.AdjustmentRule.CreateAdjustmentRule (
                DateTime.MinValue.Date, DateTime.MaxValue.Date, new TimeSpan (1, 0, 0),
                transitionToDaylight, transitionToStandard);
            var timeZone = TimeZoneInfo.CreateCustomTimeZone (
                "BugCheck", new TimeSpan (-8, 0, 0), "Testing", "Testing Standard", "Testing Daylight",
                new TimeZoneInfo.AdjustmentRule[] { adjustment });
            // See if March 7, 2014 is listed as being during daylight saving time.
            // If it is DST, then the runtime has the bug that we are looking for.
            return !timeZone.IsDaylightSavingTime (new DateTime (2014, 3, 7, 12, 0, 0, DateTimeKind.Unspecified));

Looking at the code for class TimeZoneInfo at https://github.com/mono/mono/blob/master/mcs/class/System.Core/System/TimeZoneInfo.cs , the buggy code appears to be in TimeZoneInfo.TransitionPoint(), line 1089:
    int day = 1 + (transition.Week - 1) * 7 + (transition.DayOfWeek - first) % 7;
That line should be:
    int day = 1 + (transition.Week - 1) * 7 + ((transition.DayOfWeek - first) + 7) % 7;
Comment 1 marcos.henrich 2015-01-14 09:53:04 UTC
The following pull request fixes the issue:
Comment 2 marcos.henrich 2015-01-15 06:45:24 UTC
Fixed in mono master bc6ea9d725bddb937306b0a28ee4fad77bccd96a.