Skip to content
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

Dst leap is passed on to subsequent occurrences of recuring events #648

Open
schreven opened this issue Apr 22, 2024 · 11 comments
Open

Dst leap is passed on to subsequent occurrences of recuring events #648

schreven opened this issue Apr 22, 2024 · 11 comments

Comments

@schreven
Copy link

When an occurrence of a recurring event falls exactly on a DST transition, the subsequent occurrences are also shifted forward in time, though they should not be.

I reproduced this in: #647

I've explored a quick way of fixing it, but it was not robust enough. I can share more information if it helps

@phil-davis
Copy link
Contributor

"When an occurrence of a recurring event falls exactly on/in a DST transition, the subsequent occurrences are also shifted forward in time, though they should not be."

"on/in" - just trying to be clearer that this problem happens when exactly at the time the transition "jumps" (usually 0200), or for any time in the "missing" hour (0201 to 0259 inclusive)

And I wonder what happens for other "edge cases", like someone wants an event to start at 0100 and end at 0400 - on "normal" mornings the event has a duration of 3 hours. Should the event still happen from 0100 to 0400 on the summer time transition day, and only actually have a duration of 2 hours? (and when transitioning back at the end of summer time, the event would have a duration of 4 hours?) Maybe the expected behavior is specified in an RFC somewhere - I haven't looked for that yet!

@phil-davis
Copy link
Contributor

I've explored a quick way of fixing it, but it was not robust enough. I can share more information if it helps.

Yes please - what have you tried?

@phil-davis
Copy link
Contributor

Note for reference: https://datatracker.ietf.org/doc/html/rfc5545

      If, based on the definition of the referenced time zone, the local
      time described occurs more than once (when changing from daylight
      to standard time), the DATE-TIME value refers to the first
      occurrence of the referenced time.  Thus, TZID=America/
      New_York:20071104T013000 indicates November 4, 2007 at 1:30 A.M.
      EDT (UTC-04:00).  If the local time described does not occur (when
      changing from standard to daylight time), the DATE-TIME value is
      interpreted using the UTC offset before the gap in local times.
      Thus, TZID=America/New_York:20070311T023000 indicates March 11,
      2007 at 3:30 A.M. EDT (UTC-04:00), one hour after 1:30 A.M. EST
      (UTC-05:00).

so the "jump" to 0330 on the day when 0230 does not exist, that is the correct behavior for just that day.

@schreven
Copy link
Author

schreven commented May 7, 2024

"on/in" - just trying to be clearer that this problem happens when exactly at the time the transition "jumps" (usually 0200), or for any time in the "missing" hour (0201 to 0259 inclusive)

The issue is visible for any time between 2:00 am to 2:59 am inclusive.

As you pointed out in you next comment with the rfc quote, that's the time range that does not occur and will result in a one hour "jump" forward. That jump is correct but it should be only on that event, not on subsequent occurrences.

@schreven
Copy link
Author

schreven commented May 7, 2024

Here is what I tried: https://github.com/ProtonMail/vobject/pull/101/files

note: this PR is on a fork that has diverged a bit

In short the idea is to keep track of the "jump", and to subtract it at the next occurrence. I decided to abandon it because it didn't seem sufficiently robust or future proof.

The implementation was aimed towards cases where there is a single time-modification per RruleIterator::next() execution. What worried me are the subloops, such as inside RruleIterator::nextDaily(), here. They are handled but I feel like they are error-prone.

On top of that I was forced to re-implement substractDates() and substractIntervals() which feels wrong. I had to do so because the built-in functions would have an undesired behaviour right around the DST jump.

@schreven
Copy link
Author

schreven commented May 7, 2024

Reverting the time after the fact is not ideal.

In an ideal world I would rather see the code store the "raw" datetime, i.e. 2:15am inside $this->currentTime. The transformation from 2:15am to 3:15am could then be done only on the returned occurrence. But I'm not sure that's possible with the datetime object.

@phil-davis
Copy link
Contributor

phil-davis commented May 7, 2024

Reverting the time after the fact is not ideal.

Yes, the code/object should always "know" that the real desired time for the event is 0215, and whenever it finds that 0215 does not exist, it just jumps that one occurrence to happen at 0315, then continues on calculating more future dates on which the event will happen at 0215. (And it is possible that an event like this, that happens regularly at 0215, and runs for a few years, will have multiple occurrences that need to happen at 0315!)

@gharlan
Copy link
Contributor

gharlan commented May 8, 2024

And I wonder what happens for other "edge cases", like someone wants an event to start at 0100 and end at 0400 - on "normal" mornings the event has a duration of 3 hours. Should the event still happen from 0100 to 0400 on the summer time transition day, and only actually have a duration of 2 hours? (and when transitioning back at the end of summer time, the event would have a duration of 4 hours?) Maybe the expected behavior is specified in an RFC somewhere - I haven't looked for that yet!

Google and Apple behave differently here.

  • On Google calendar, the event always has a duration of 3 hours. So on the transition days the event ends at 0500 and 0300.
  • On Apple calendar, the event always ends at 0400. So on the transition days the event duration is 2h and 4h.

I don't know which one is correct.

@phil-davis
Copy link
Contributor

phil-davis commented May 8, 2024

I don't know which one is correct.

And either is "correct" depending on what the user wants! For example, I have worked in places with 24hr shift rosters. On the time transition nights, an 8-hour shift would actually only be 7-hours elapsed time on one transition, and 9-hours elapsed time on the other transition. That allowed the day shift to start always at the same time on the local clock.

But other organizations might want different behavior - there is no way to know, the RFC does not provide any way for the user to select which behavior they want.

@gharlan
Copy link
Contributor

gharlan commented May 8, 2024

there is no way to know, the RFC does not provide any way for the user to select which behavior they want.

A recurring VEVENT with DTSTART and DURATION (without DTEND) would explicitly require a specific duration.
But most calendar tools don't allow to switch between DTEND and DURATION, they always use DTEND.

@gharlan
Copy link
Contributor

gharlan commented May 8, 2024

But because the RFC supports DURATION for a constant duration, I think for DTEND the apple behavior is more correct (specific end time).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants