Skip to content

Commit 513f284

Browse files
author
CipherdevNL
committed
fix: skipped run after daylight saving turnover point
1 parent f37e405 commit 513f284

File tree

2 files changed

+65
-16
lines changed

2 files changed

+65
-16
lines changed

src/Cron/HoursField.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,7 @@ public function increment(DateTimeInterface &$date, $invert = false, $parts = nu
167167
if (! $invert) {
168168
if ($originalHour >= $target) {
169169
$distance = 24 - $originalHour;
170-
$date = $this->timezoneSafeModify($date, "+{$distance} hours");
170+
$date = $date->modify("+{$distance} hours");
171171

172172
$actualDay = (int)$date->format('d');
173173
$actualHour = (int)$date->format('H');
@@ -180,7 +180,7 @@ public function increment(DateTimeInterface &$date, $invert = false, $parts = nu
180180
}
181181

182182
$distance = $target - $originalHour;
183-
$date = $this->timezoneSafeModify($date, "+{$distance} hours");
183+
$date = $date->modify("+{$distance} hours");
184184
} else {
185185
if ($originalHour <= $target) {
186186
$distance = ($originalHour + 1);

tests/Cron/DaylightSavingsTest.php

Lines changed: 63 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -209,28 +209,77 @@ public function testOffsetDecrementsPreviousRunDate(): void
209209
$this->assertEquals($dtExpected, $cron->getPreviousRunDate($dtCurrent, 0, false, $tz->getName()));
210210
}
211211

212-
public function testOffsetIncrementsMultipleRunDates(): void
212+
public static function dayLightSavingExamples(): \Generator
213213
{
214-
$expression = "0 1 * * 0";
215-
$cron = new CronExpression($expression);
216-
$tz = new \DateTimeZone("Europe/London");
214+
yield 'fixed hour before turnover point' => [
215+
"0 1 * * 0",
216+
[
217+
"2021-03-14 01:00+00:00",
218+
"2021-03-21 01:00+00:00",
219+
"2021-03-28 02:00+01:00",
220+
"2021-04-04 01:00+01:00",
221+
"2021-04-11 01:00+01:00",
222+
],
223+
new \DateTimeZone("Europe/London"),
224+
"2021-03-13 00:00+00:00",
225+
"2021-04-12 00:00+01:00",
226+
];
217227

218-
$expected = [
219-
$this->createDateTimeExactly("2021-03-14 01:00+00:00", $tz),
220-
$this->createDateTimeExactly("2021-03-21 01:00+00:00", $tz),
221-
$this->createDateTimeExactly("2021-03-28 02:00+01:00", $tz),
222-
$this->createDateTimeExactly("2021-04-04 01:00+01:00", $tz),
223-
$this->createDateTimeExactly("2021-04-11 01:00+01:00", $tz),
228+
yield 'fixed hour after turnover point #202' => [
229+
"0 10 * * *",
230+
[
231+
"2025-03-08 10:00-06:00",
232+
"2025-03-09 10:00-05:00",
233+
"2025-03-10 10:00-05:00",
234+
],
235+
new \DateTimeZone("America/Chicago"),
236+
"2025-03-08 09:00-06:00",
237+
"2025-03-10 11:00-05:00",
224238
];
225239

226-
$dtCurrent = $this->createDateTimeExactly("2021-03-13 00:00+00:00", $tz);
227-
$actual = $cron->getMultipleRunDates(5, $dtCurrent, false, true, $tz->getName());
240+
yield 'fixed hour after turnover point #154' => [
241+
"30 07 * * *",
242+
[
243+
"2023-03-11 07:30-05:00",
244+
"2023-03-12 07:30-04:00",
245+
"2023-03-13 07:30-04:00",
246+
],
247+
new \DateTimeZone("America/New_York"),
248+
"2023-03-10 08:00-05:00",
249+
"2023-03-13 08:00-04:00",
250+
];
251+
}
252+
253+
/**
254+
* @param string[] $expected
255+
*
256+
* @dataProvider dayLightSavingExamples
257+
*/
258+
public function testOffsetIncrementsMultipleRunDates(
259+
string $expression,
260+
array $expected,
261+
\DateTimeZone $tz,
262+
string $currentDate,
263+
string $currentInvertedDate
264+
): void {
265+
$cron = new CronExpression($expression);
266+
267+
$expected = array_map(
268+
function (string $dtString) use ($tz) {
269+
return $this->createDateTimeExactly($dtString, $tz);
270+
},
271+
$expected
272+
);
273+
$total = count($expected);
274+
275+
$dtCurrent = $this->createDateTimeExactly($currentDate, $tz);
276+
$actual = $cron->getMultipleRunDates($total, $dtCurrent, false, true, $tz->getName());
228277
foreach ($expected as $dtExpected) {
229278
$this->assertContainsEquals($dtExpected, $actual);
230279
}
231280

232-
$dtCurrent = $this->createDateTimeExactly("2021-04-12 00:00+01:00", $tz);
233-
$actual = $cron->getMultipleRunDates(5, $dtCurrent, true, true, $tz->getName());
281+
$dtCurrent = $this->createDateTimeExactly($currentInvertedDate, $tz);
282+
$actual = $cron->getMultipleRunDates($total, $dtCurrent, true, true, $tz->getName());
234283
foreach ($expected as $dtExpected) {
235284
$this->assertContainsEquals($dtExpected, $actual);
236285
}

0 commit comments

Comments
 (0)