Skip to content

Commit

Permalink
Handle summer time start for weekly recurrences
Browse files Browse the repository at this point in the history
  • Loading branch information
phil-davis committed May 9, 2024
1 parent dc7ff2a commit 8f04468
Show file tree
Hide file tree
Showing 2 changed files with 76 additions and 2 deletions.
16 changes: 16 additions & 0 deletions lib/Recur/RRuleIterator.php
Original file line number Diff line number Diff line change
Expand Up @@ -373,7 +373,23 @@ protected function nextDaily(): void
protected function nextWeekly(): void
{
if (!$this->byHour && !$this->byDay) {
$hourOfCurrentDate = (int) $this->currentDate->format('G');
$this->currentDate = $this->currentDate->modify('+'.$this->interval.' weeks');
$hourOfNextDate = (int) $this->currentDate->format('G');
if (0 === $this->hourJump) {
// Remember if the clock time jumped forward on the nextDate.
// That happens if nextDate is a day when summer time starts
// and the event time is in the non-existent hour of the day.
// For example, an event that normally starts at 02:30 will
// have to start at 03:30 on that day.
$this->hourJump = $hourOfNextDate - $hourOfCurrentDate;
} else {
// The hour "jumped" for the previous date, to avoid the non-existent time.
// currentDate got set ahead by (usually) one hour on that day.
// Adjust it back for this next occurrence.
$this->currentDate = $this->currentDate->sub(new \DateInterval('PT'.$this->hourJump.'H'));
$this->hourJump = 0;
}

return;
}
Expand Down
62 changes: 60 additions & 2 deletions tests/VObject/Recur/RRuleIteratorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ public function testDailyBySetPosLoop(): void
}

/**
* @dataProvider dstTransitionProvider
* @dataProvider dstDailyTransitionProvider
*/
public function testDailyOnDstTransition(string $start, array $expected): void
{
Expand All @@ -176,7 +176,7 @@ public function testDailyOnDstTransition(string $start, array $expected): void
);
}

public function dstTransitionProvider(): iterable
public function dstDailyTransitionProvider(): iterable
{
yield 'On transition start' => [
'Start' => '2023-03-24 02:00:00',
Expand Down Expand Up @@ -323,6 +323,64 @@ public function testWeeklyByDaySpecificHour(): void
);
}

/**
* @dataProvider dstWeeklyTransitionProvider
*/
public function testWeeklyOnDstTransition(string $start, array $expected): void
{
$this->parse(
'FREQ=WEEKLY;INTERVAL=1;COUNT=5',
$start,
$expected,
null,
'Europe/Zurich',
);
}

public function dstWeeklyTransitionProvider(): iterable
{
yield 'On transition start' => [
'Start' => '2023-03-12 02:00:00',
'Expected' => [
'2023-03-12 02:00:00',
'2023-03-19 02:00:00',
'2023-03-26 03:00:00',
'2023-04-02 02:00:00',
'2023-04-09 02:00:00',
],
];
yield 'During transition' => [
'Start' => '2023-03-12 02:15:00',
'Expected' => [
'2023-03-12 02:15:00',
'2023-03-19 02:15:00',
'2023-03-26 03:15:00',
'2023-04-02 02:15:00',
'2023-04-09 02:15:00',
],
];
yield 'On transition end' => [
'Start' => '2023-03-12 03:00:00',
'Expected' => [
'2023-03-12 03:00:00',
'2023-03-19 03:00:00',
'2023-03-26 03:00:00',
'2023-04-02 03:00:00',
'2023-04-09 03:00:00',
],
];
yield 'After transition end' => [
'Start' => '2023-03-12 03:15:00',
'Expected' => [
'2023-03-12 03:15:00',
'2023-03-19 03:15:00',
'2023-03-26 03:15:00',
'2023-04-02 03:15:00',
'2023-04-09 03:15:00',
],
];
}

public function testMonthly(): void
{
$this->parse(
Expand Down

0 comments on commit 8f04468

Please sign in to comment.