-
Notifications
You must be signed in to change notification settings - Fork 126
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
Handle summer time jumps in event recurrences #653
Conversation
Codecov ReportAll modified and coverable lines are covered by tests ✅
Additional details and impacted files@@ Coverage Diff @@
## master #653 +/- ##
=========================================
Coverage 98.78% 98.78%
- Complexity 1870 1875 +5
=========================================
Files 71 71
Lines 5256 5273 +17
=========================================
+ Hits 5192 5209 +17
Misses 64 64 ☔ View full report in Codecov by Sentry. |
It looks better than my attempt. In the end wasn't it possible to store the "unaltered" datetime as mentioned here? One idea would be to have a new object that extends DateTime and overrides |
The "unaltered" time, for example "0230" is not a valid time on the date when summer time starts. So the There are other possible edge-cases, but they don't really happen. For example, if 2 recurrences in a row fall on the summer time start date, then reversing the hour-jump would have to be delayed. But in real-life, summer time usually starts on a Sunday morning. For a yearly event, the recurrence in the next year is always 1 or 2 days later in the week, so there can't be 2 Sunday's in a row for a yearly event. But someone could design an event that happens at 0230 every 52nd Sunday - and that could fall on the summer time start date for a few years in a row! |
a2e53c3
to
663937e
Compare
@@ -349,7 +392,7 @@ protected function nextDaily(): void | |||
protected function nextWeekly(): void | |||
{ | |||
if (!$this->byHour && !$this->byDay) { | |||
$this->currentDate = $this->currentDate->modify('+'.$this->interval.' weeks'); | |||
$this->advanceTheDate('+'.$this->interval.' weeks'); | |||
|
|||
return; | |||
} |
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.
Question: Should we not handle the execution going to the rest of the function as well? I would well see a line at the very end to set the time straight:
$this->startDate->modify($this->startDate->format('H:i:s'));
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.
This is a bit trickier. I will try have a look tonight. I just need to make sure that various BYDAY BYHOUR etc filters will skip along correctly while sometimes happening to hit a summer-time start day. There might be a few code paths to think about (or it might turn out to be easy!)
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.
I have done the scenario for WEEKLY BYDAY when the recurrence falls on Sunday at 0230.
It is trickier for: FREQ=WEEKLY;INTERVAL=2;BYDAY=SA,SU;WKST=MO;BYHOUR=2,14
The RRULE says to schedule at 0200 and 1400 on each Saturday and Sunday.
On the Sunday of summer-time transition there is no 0200. The code current skips scheduling anything on the Sunday morning of summer-time transition. Future recurrences on later weekends are correctly scheduled at 0200 and 1400.
The "bug" in this case is not that the scheduled time gets locked forward to 0300, but that the recurrence on the summer-time transition day is not scheduled at all.
The RFC does not say anything about what is required if one of the hours mentioned in BYHOUR does not exist on the day in question.
I pushed a test case for now, that demonstrates the current behavior.
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.
@schreven I have handled all the cases that I could see where nextWeekly
netMonthly
or nextYearly
have BYDAY or similar specified and the resulting day in the week, month or year might fall on a summer-time start date.
There are test cases and code fixes for all that.
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.
Got it, thanks for the details
The "bug" in this case is not that the scheduled time gets locked forward to 0300, but that the recurrence on the summer-time transition day is not scheduled at all
Indeed that appears like a separate question that is out of scope
Looks good to me overall, with all the tests it's convincing that it behaves correctly
I have not tried to change the behavior when a weekly, monthly, yearly etc. rule has BYHOUR that ends up specifying that the event occurs in the 0200 hour. In that case, the client has specifically asked for a time like 0200, and on the summer-time transition day that hour does not exist. The current code logic does not move the event to 0300, it does not schedule an event at all for that potential recurrence. Firstly, the desired behavior needs to be defined. Then if different from the current code logic, a PR can be done. I think that this PR is big enough already, and covers the more likely cases when this summer-time thing happens. So please review. |
Also note: this library does not currently support BYHOUR with MONTHLY or YEARLY RRULEs. So in And this library does not do anything with BYMINUTE or BYSECOND, so there is no need to consider what might happen for rules that are requested to happen multiple times each hour etc. |
@@ -349,7 +392,7 @@ protected function nextDaily(): void | |||
protected function nextWeekly(): void | |||
{ | |||
if (!$this->byHour && !$this->byDay) { | |||
$this->currentDate = $this->currentDate->modify('+'.$this->interval.' weeks'); | |||
$this->advanceTheDate('+'.$this->interval.' weeks'); | |||
|
|||
return; | |||
} |
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.
Got it, thanks for the details
The "bug" in this case is not that the scheduled time gets locked forward to 0300, but that the recurrence on the summer-time transition day is not scheduled at all
Indeed that appears like a separate question that is out of scope
Looks good to me overall, with all the tests it's convincing that it behaves correctly
Backport to 4.5 release branch is PR #660 |
Issue #648
1st commit is the test code added by @schreven in PR #647
2nd commit is my first code that makes those test cases pass. It only touches the case of events that recur at an interval of days.
nextHourly
Thanks to @gharlan and @schreven for input, code suggestions etc.