-
Notifications
You must be signed in to change notification settings - Fork 131
Fix a bug related to rare DST cases because of wrong DateTime convertation between time zones on Windows #37
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
The reason is DST rules in Chile was changed in 2017 and on early versions of Ubuntu time zone data base has wrong information about DST in 2021.
|
Awesome, thanks a lot for the investigation! I have some questions, since it potentially can break some use cases, so we need to think and implement it carefully.
Is this information available anywhere to read about it, e.g. how did you learn about these numbers?
Does
Does this decision cause any breaking changes? Consider we are using the following code (I understand it can cause problems with var fromUtc = /* Some Date */;
var expression = /* Some Expression */;
while (/* SomeCondition */)
{
fromUtc = expression.GetNextOccurrence(fromUtc.AddTicks(1), chileTimeZone, inclusive: true);
}As far as I understand these changes will break the behaviour (more over, it will cause an endless loop), right? |
I did not find any official information about it. But TimeZoneInfo provides API to get DST time transisition for certain date. And I used this API to get a list of time zones with wrong info about DST. Firstly I added to the list a few extra time zones by mistake. Now, I rewrote my code and got 17 such zones (Last time I took into account zones with And there are only 6 time zones that have wrong actual (that applies now, not in the past) rule with wrong DST info (I published the code to GitHub and .NET Fiddle if somebody wants to check it).
It's interesting that all incorrect DST time transitions are exactly
The changes should not lead to breaking changes. In your example the behavior will be as the same as before the changes. You add 1 tick to avoid endless loop and get new result at each iteration with So the following code: is equivalent (almost, actually we don't round I added tests to check making progress inside iteration. |
…ionRuleIsAppliedDueToDST test
odinserj
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Andrew, thank you for such a brilliant work! I was unsure whether one corner case works fine, so I've added another test (actually this test was the reason for the delay). Sorry for the delay, now I see everything works perfectly, so I'm merging this PR. Thank you so much!
This PR fixes rare case reproduced on Windows and related to daylight saving time (DST) transiton.
DateTime convertation bug on Windows
There are 49 of 141 Windows time zones which have not totally accurate daylight transtion time information.
Consider time zone Chile Time (Windows time zone id: Pacific SA Standard Time) as example. Chile Standard Time (CST) is 4 hours before UTC, and Chile Summer Time (CLST) - 3 hours before UTC.
1. DST start case for Chile time zone.
In 2021 DST starts when clocks jump forward from 2021-09-05 00:00 -4:00 CST to 2021-09-05 01:00 -3:00 CLST.
So local time
[2021-09-05 00:00, 2021-09-05 01:00)does not exist.time -> _____23:59:59.9999999 -04:00 CST////invalid////01:00:00.0000000 -03:00 CLST
But in Windows time zone data base transition time is not
00:00:00but23:59:59.9990000- 10000 ticks before.As as result, convertation from 2021-09-05 03:59:59.9990000 UTC to Chile time equals 2021-09-05 00:59:59.9990000 -3:00 CLST instead of 2021-09-04 23:59:59.9990000 -4:00 CST. See code below:
2. DST end case for Chile time zone.
It's the similar behavior for DST end. Clocks jump backward from 2021-04-04 00:00 -3:00 CLST to 2021-04-03 23:00 -4:00 CLT.
So local time
[2021-04-03 23:00, 2021-04-04 00:00)is ambiguous.time -> ____23:00 -03:00____23:59:59.9999999 -03:00 CST -> 23:00:00.0000000 -04:00 CLST
And convertation from 2021-04-04 02:59:59.9990000 UTC to Chile time equals 2021-04-04 22:59:59.9990000 -4:00 CLT instead of 2021-04-04 23:59:59.9990000 -3:00 CST.
Consequences for Cronos
Due to these rounding errors Cronos can skip some occurrences when DST starts:
Or even get occurrence from the past when DST ends:
Decision
We can just floor input time to seconds and avoid such behavior.
In case of DST start we floor 2021-09-05 03:59:59.9990000 UTC to 2021-09-05 03:59:59.0000000 UTC.
Then convertation from 2021-09-05 03:59:59.0000000 UTC to Chile time equals 2021-09-04 23:59:59.0000000 -4:00 CST instead of wrong 2021-09-05 00:59:59.9990000 -3:00 CLST.
Also we have to set
inclusive = false. Otherwise floored time can match cron expression and be returned as result, but it'l be wrong because result will be less than passed from argument.