[php-src] Issue #18875: "Same" DateInterval instances lead to different results, depending on the origin (in combination with DST-switches)
| From: | cziegenberg | Date: | Thu, 19 Jun 2025 08:57:02 +0000 |
| Subject: | [php-src] Issue #18875: "Same" DateInterval instances lead to different results, depending on the origin (in combination with DST-switches) | ||
| Groups: | php.bugs | ||
| Request: | Send a blank email to php-bugs+get-250279@lists.php.net to get a copy of this message | ||
Issue: https://github.com/php/php-src/issues/18875
Author: cziegenberg
### Description
The following code:
```php
<?php
function getIntervalSpecificationFromDateInterval(DateInterval $interval): string
{
$specification = '';
if ($interval->invert) {
$specification .= '-';
}
$specification .= 'P';
$specification .= $interval->y ? $interval->y . 'Y' : '';
$specification .= $interval->m ? $interval->m . 'M' : '';
$specification .= $interval->d ? $interval->d . 'D' : '';
if ($interval->h + $interval->i + $interval->s) {
$specification .= 'T';
$specification .= $interval->h ? $interval->h . 'H' : '';
$specification .= $interval->i ? $interval->i . 'M' : '';
$specification .= $interval->s ? $interval->s . 'S' : '';
}
if ($specification === 'P' || $specification === '-P') {
$specification = 'PT0S';
}
return $specification;
}
$timezone = new DateTimeZone('Europe/Berlin');
$dstSwitchA = new DateTimeImmutable('2025-03-30 01:00:00', $timezone);
$dstSwitchB = new DateTimeImmutable('2025-10-26 01:00:00', $timezone);
$durationA = new DateInterval('PT3H');
$durationB = (new DateTimeImmutable('2025-03-28 01:00:00', $timezone))->diff(
new DateTimeImmutable('2025-03-28 04:00:00', $timezone),
true
);
$durationC = (new DateTimeImmutable('2025-03-28 01:00:00', $timezone))->diff(
new DateTimeImmutable('2025-03-28 04:00:00', $timezone),
);
$durationD = (new DateTimeImmutable('2025-03-28 01:00:00', $timezone))->diff(
new DateTimeImmutable('2025-03-28 04:00:00', $timezone),
);
$durationD = new DateInterval(getIntervalSpecificationFromDateInterval($durationD));
// Test 1st DST-switch (+1 hour)
echo 'TEST 1 (DST-switch +1 hour)' . PHP_EOL;
$datetimeA = $dstSwitchA->setTimezone($timezone)->add($durationA);
echo 'Constructed: ' . $datetimeA->format('Y-m-d H:i:s') . PHP_EOL; //
expected: 2025-03-30 05:00:00
$datetimeB = $dstSwitchA->setTimezone($timezone)->add($durationB);
echo 'Diff (absolute): ' . $datetimeB->format('Y-m-d H:i:s') . PHP_EOL; //
expected: 2025-03-30 05:00:00
$datetimeC = $dstSwitchA->setTimezone($timezone)->add($durationC);
echo 'Diff (relative): ' . $datetimeC->format('Y-m-d H:i:s') . PHP_EOL; //
expected: 2025-03-30 05:00:00
$datetimeD = $dstSwitchA->setTimezone($timezone)->add($durationD);
echo 'Workaround: ' . $datetimeD->format('Y-m-d H:i:s') . PHP_EOL; //
expected: 2025-03-30 05:00:00
echo PHP_EOL;
echo 'TEST 2 (DST-switch -1 hour)' . PHP_EOL;
// Test 2nd DST-switch (-1 hour)
// Expected value: 2025-10-26 03:00:00
$datetimeA = $dstSwitchB->setTimezone($timezone)->add($durationA);
echo 'Constructed: ' . $datetimeA->format('Y-m-d H:i:s') . PHP_EOL;
$datetimeB = $dstSwitchB->setTimezone($timezone)->add($durationB);
echo 'Diff (absolute): ' . $datetimeB->format('Y-m-d H:i:s') . PHP_EOL;
$datetimeC = $dstSwitchB->setTimezone($timezone)->add($durationC);
echo 'Diff (relative): ' . $datetimeC->format('Y-m-d H:i:s') . PHP_EOL;
$datetimeD = $dstSwitchB->setTimezone($timezone)->add($durationD);
echo 'Workaround: ' . $datetimeD->format('Y-m-d H:i:s') . PHP_EOL;
```
Resulted in this output:
```
TEST 1 (DST-switch +1 hour)
Constructed: 2025-03-30 05:00:00
Diff (absolute): 2025-03-30 04:00:00
Diff (relative): 2025-03-30 04:00:00
Workaround: 2025-03-30 05:00:00
TEST 2 (DST-switch -1 hour)
Constructed: 2025-10-26 03:00:00
Diff (absolute): 2025-10-26 04:00:00
Diff (relative): 2025-10-26 04:00:00
Workaround: 2025-10-26 03:00:00
```
But I expected this output instead:
```
TEST 1 (DST-switch +1 hour)
Constructed: 2025-03-30 05:00:00
Diff (absolute): 2025-03-30 05:00:00
Diff (relative): 2025-03-30 05:00:00
Workaround: 2025-03-30 05:00:00
TEST 2 (DST-switch -1 hour)
Constructed: 2025-10-26 03:00:00
Diff (absolute): 2025-10-26 03:00:00
Diff (relative): 2025-10-26 03:00:00
Workaround: 2025-10-26 03:00:00
```
### PHP Version
```plain
PHP 8.3.16 (cli) (built: Jan 14 2025 20:07:09) (NTS Visual C++ 2019 x64)
Copyright (c) The PHP Group
Zend Engine v4.3.16, Copyright (c) Zend Technologies
with Zend OPcache v8.3.16, Copyright (c), by Zend Technologies
with Xdebug v3.4.1, Copyright (c) 2002-2025, by Derick Rethans
Tested with PHP 8.1.0 to 8.4.8
```
### Operating System
_No response_