-
Notifications
You must be signed in to change notification settings - Fork 358
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
Daily rule occurs twice in a day when start is in last DST hour #189
Comments
https://github.com/forrest/ice_cube/compare/189_fix has the failing spec added. |
I'm not seeing the failure here:
What's your system TZ by the way? ( |
Ok, I'm seeing the error now with |
It fails if I get rid of the zone info all together:
or if I specify the zone.parse
|
Here's what I see:
Note the change in time zone between 1 and 2. Pretty sure this only affects daily rules... I was positive I had a test case for this in daily_rule_spec. 😒 |
You have a very similar test just above where I placed mine. Don't know why it's passing in one case and failing in another. My infinite loop is partly based on the use in my code. I reset the day each time, so it's resetting back to -06:00. I can fix mine to avoid the loop. Unfortunately we'll still have an incorrect date in the middle of the run. |
Hey Forrest, I changed the title from "infinite loop" since that's not an accurate description: this issue is actually a pretty unique and somewhat interesting edge case. Allow me to expand on what's actually happening: When DST is ending, the clock time "01:00:00" to "01:59:59" happens twice: once in summer/daylight time, and again when the clock rolls back to standard time. I distinguish these two instances of "1 AM" as the last hour of daylight time, and the first hour of standard time:
You'll find it's actually fairly unnatural to create a local Time within the DT Last Hour:
These two look like they should be one second apart, in fact they are 1 hour + 1 second apart; the whole DT Last Hour is skipped. You can fool it with IceCube also jumps over the DT Last Hour when traversing daily rules, so that:
The only time you'll run into your double-occurrence problem is when you explicitly create a daily schedule that starts within DT Last Hour. Normally when traversing over DST, the intervals between daily occurrences are:
(In March there's a 23 hours) When you create a schedule that actually starts in DT Last Hour, that's not a "normal" time we'd ever traverse for a daily rule, so your initial start time before the schedule adjusts itself to get on the right track is an extra:
I would recommend not creating things that start in DT Last Hour. Traversing over it works fine, just not as the start time. I suppose that's not 100% avoidable, so it might be reasonable to skip the "correct" scheduled daily occurrence for Nov 3 so there aren't two occurrences on the same day. It just means the 25-hour interval happens one day later than normal:
Does that make sense? |
Hey @avit, Is it possible to add a check in |
What Would iCal Do? This is:
That first occurrence is also 2 hours long, but the second 1AM is not shown. There is no second occurrence after the clock change, and the 1 hour time difference is deferred until the next day. That's what I was suggesting, so let's do it that way. (I haven't looked at fixing this yet, @ajsharp are you keen to take a look?) |
@avit Thanks for mapping this out. I don't have time to dig into this issue this week, but I might next. For clarity's sake, let me see if I have this straight:
So, in iCal you scheduled a recurring daily two-hour appointment on Sunday. Are you saying that the occurrence on November 3rd at 1AM (the last hour of daylight savings time) was basically cut into two one-hour occurrences? One one-hour occurrence that began at 1am before the clock rolled back, and one one-hour occurrence that occurred after the clock rolled back, also at 1am? I think that makes sense (insofar as daylight savings itself "makes sense"). Disclaimer: I haven't thought about this problem nearly as hard as you guys have, so please excuse any ignorance around this :) |
No. It's still one occurrence, duration 2 hours, but, there's only one "1 AM" shown on the grid. The other days are also 2h durations, so they stop at 2:59:59 instead. Just for giggles, I tried creating an event for each "1AM", and they show up side-by-side even though they're 1 hour apart: Not that this has anything to do with IceCube, just showing that everyone has their own problems dealing with DST.
Totally... 😖 |
Ah, got it, thanks for explaining. That handling makes sense for this particular example (a 2-hour appointment where the first hour coincides with the last hour of daylight savings). However, let me throw out a couple of other examples that don't quite compute to me, at least not in a way that I can think about them in an algorithmic way:
|
No problem here. First hour of ST has already rolled over and is "on track".
We convert end_time into duration internally, so whatever is the duration of the first occurrence will extend to all occurrences. In this case, because it's created in that limbo hour, the occurrences will have an extra hour duration if you defined it using an end_time. Note from my first iCal screenshot above, it looks like I'm setting up 1:00AM to 2:00AM, which looks like 1 hour duration... but actually it's two hours because of the time difference from 1:00AM DT to 2:00AM ST. |
Simplify the method we use for calculating time changes across DST boundaries by performing arithmetic under UTC to get "absolute" values. This is a revert of the "unrolling in pairs" method introduced in c93fa7e for fixing ice-cube-ruby#189. The method of converting to UTC and back for doing time arithmetic only applies when DST needs to be taken into consideration. For rules with less than daily intervals, both hours still need to occur. This distinction was added in the original fix. However, the method was not correctly tested for non-ActiveSupport times (local system TZ) and the advancing of time to the next occurrence was validating both the last DT hour (before fall back) and first ST hour (after fall back) causing double occurrences for the "same" hour on the clock face. Fixes ice-cube-ruby#398
Hey,
Getting this infinite loop causing all kinds of chaos right now. Any help would be greatly appreciated.
Forrest
The text was updated successfully, but these errors were encountered: