|
2 | 2 | Bug GH-21616 (DateTime::modify() does not respect DST transitions) |
3 | 3 | --FILE-- |
4 | 4 | <?php |
5 | | -/* Spring forward: Europe/London, 2025-03-30 01:00 GMT -> 02:00 BST. |
6 | | - * Subtracting 1 second from 02:00:00 BST must land at 00:59:59 GMT, |
7 | | - * not at 02:59:59 BST. */ |
| 5 | +/* Spring forward: Europe/London, 2025-03-30 01:00 GMT -> 02:00 BST */ |
8 | 6 | $tz = new DateTimeZone('Europe/London'); |
9 | 7 |
|
10 | | -echo "=== Spring forward ===\n"; |
11 | | - |
12 | | -echo "modify +1s then -1s:\n"; |
| 8 | +/* +1s then -1s must round-trip */ |
13 | 9 | $dt = new DateTime('2025-03-30 00:59:59', $tz); |
14 | 10 | $dt->modify('+1 second'); |
15 | 11 | $dt->modify('-1 second'); |
16 | 12 | echo $dt->format('Y-m-d H:i:s T U'), "\n"; |
17 | 13 |
|
18 | | -echo "add/sub PT1S (reference):\n"; |
19 | | -$dt2 = new DateTime('2025-03-30 00:59:59', $tz); |
20 | | -$dt2->add(new DateInterval('PT1S')); |
21 | | -$dt2->sub(new DateInterval('PT1S')); |
22 | | -echo $dt2->format('Y-m-d H:i:s T U'), "\n"; |
23 | | - |
24 | | -echo "modify -1s from 02:00 BST:\n"; |
25 | | -$dt3 = new DateTime('2025-03-30 02:00:00', $tz); |
26 | | -echo $dt3->modify('-1 second')->format('Y-m-d H:i:s T U'), "\n"; |
| 14 | +/* -1s from 02:00 BST must land at 00:59:59 GMT, not 02:59:59 BST */ |
| 15 | +$dt2 = new DateTime('2025-03-30 02:00:00', $tz); |
| 16 | +echo $dt2->modify('-1 second')->format('Y-m-d H:i:s T U'), "\n"; |
27 | 17 |
|
28 | | -echo "\n=== Combined relative (month + hours near DST) ===\n"; |
| 18 | +/* month + hours: +1 month lands before the DST boundary, so +1 hour is plain GMT */ |
| 19 | +$dt3 = new DateTime('2025-02-28 00:30:00', $tz); |
| 20 | +echo $dt3->modify('+1 month +1 hour')->format('Y-m-d H:i:s T U'), "\n"; |
29 | 21 |
|
30 | | -/* 2025-02-28 00:30:00 GMT + 1 month + 1 hour should land on |
31 | | - * 2025-03-28 01:30:00 GMT (not affected by DST on March 30). */ |
32 | | -$dt4 = new DateTime('2025-02-28 00:30:00', $tz); |
33 | | -echo "modify +1 month +1 hour:\n"; |
34 | | -echo $dt4->modify('+1 month +1 hour')->format('Y-m-d H:i:s T U'), "\n"; |
| 22 | +/* first/last day of must still work */ |
| 23 | +$base = new DateTimeImmutable('2025-03-15 10:00:00', $tz); |
| 24 | +echo $base->modify('first day of next month')->format('Y-m-d H:i:s T'), "\n"; |
| 25 | +echo $base->modify('last day of this month')->format('Y-m-d H:i:s T'), "\n"; |
35 | 26 |
|
36 | | -echo "\n=== first/last day of (must not regress) ===\n"; |
| 27 | +/* +61 minutes from just before the gap -- minutes must also count as elapsed time */ |
| 28 | +$dt4 = new DateTime('2025-03-30 00:59:00', $tz); |
| 29 | +echo $dt4->modify('+61 minutes')->format('Y-m-d H:i:s T U'), "\n"; |
37 | 30 |
|
38 | | -/* Ensure first_last_day_of still works correctly. */ |
39 | | -$dt5 = new DateTime('2025-03-15 10:00:00', $tz); |
40 | | -echo "modify first day of next month:\n"; |
41 | | -echo $dt5->modify('first day of next month') |
42 | | - ->format('Y-m-d H:i:s T'), "\n"; |
43 | | - |
44 | | -$dt6 = new DateTime('2025-03-15 10:00:00', $tz); |
45 | | -echo "modify last day of this month:\n"; |
46 | | -echo $dt6->modify('last day of this month') |
47 | | - ->format('Y-m-d H:i:s T'), "\n"; |
| 31 | +/* DateTimeImmutable must behave the same as mutable DateTime */ |
| 32 | +$dt5 = new DateTimeImmutable('2025-03-30 02:00:00', $tz); |
| 33 | +echo $dt5->modify('-1 second')->format('Y-m-d H:i:s T U'), "\n"; |
48 | 34 | ?> |
49 | 35 | --EXPECT-- |
50 | | -=== Spring forward === |
51 | | -modify +1s then -1s: |
52 | | -2025-03-30 00:59:59 GMT 1743296399 |
53 | | -add/sub PT1S (reference): |
54 | 36 | 2025-03-30 00:59:59 GMT 1743296399 |
55 | | -modify -1s from 02:00 BST: |
56 | 37 | 2025-03-30 00:59:59 GMT 1743296399 |
57 | | - |
58 | | -=== Combined relative (month + hours near DST) === |
59 | | -modify +1 month +1 hour: |
60 | 38 | 2025-03-28 01:30:00 GMT 1743125400 |
61 | | - |
62 | | -=== first/last day of (must not regress) === |
63 | | -modify first day of next month: |
64 | 39 | 2025-04-01 10:00:00 BST |
65 | | -modify last day of this month: |
66 | 40 | 2025-03-31 10:00:00 BST |
| 41 | +2025-03-30 03:00:00 BST 1743300000 |
| 42 | +2025-03-30 00:59:59 GMT 1743296399 |
0 commit comments