Bug #81072 [NEW]: Incorrect behavior of DateTime->modify across DST changes

From: Date: Sat, 22 May 2021 18:55:52 +0000
Subject: Bug #81072 [NEW]: Incorrect behavior of DateTime->modify across DST changes
Groups: php.bugs 
Request: Send a blank email to php-bugs+get-233979@lists.php.net to get a copy of this message
From: ph-bugs at allenjb dot me dot uk Operating system: PHP version: 8.0.6 Package: Date/time related Bug Type: Bug Bug description:Incorrect behavior of DateTime->modify across DST changes Description: ------------ See https://3v4l.org/hGXcr Working on a fix for https://github.com/dragonmantank/cron-expression/issues/111 As you can see, when working backwards with ->modify("-1 hour") DateTime fails to properly handle the DST change and keeps pushing the time forward to 03:00:00 Working forwards with ->modify("+1 hour") does not exhibit the same behavior. (The code examples also show a workaround, which involved switching timezones while performing the ->modify) Test script: --------------- <?php function incrementWithSwitch($date, $invert) { $timezone = $date->getTimezone(); $date = $date->setTimezone(new DateTimeZone('UTC')); $date = $date->modify(($invert ? '-' : '+') . '1 hour'); $date = $date->setTimezone($timezone); $date = $date->setTime((int)$date->format('H'), 0); return $date; } function incrementWithoutSwitch($date, $invert) { $date = $date->modify(($invert ? '-' : '+') . '1 hour'); return $date; } $tz = new \DateTimeZone("Europe/London"); $dtWith = \DateTimeImmutable::createFromFormat("!Y-m-d H:i:s", "2021-03-28 04:00:00"); $dtWithout = $dtWith; $invert = true; for ($i = 0; $i < 3; $i++) { print "\nRound {$i}:"; $dtWith = incrementWithSwitch($dtWith, $invert); $dtWithout = incrementWithoutSwitch($dtWithout, $invert); print "With switch: ". $dtWith->format(\DateTime::RFC3339); print " :: Without switch: ". $dtWithout->format(\DateTime::RFC3339); } print "\n---\n"; $dtWith = \DateTimeImmutable::createFromFormat("!Y-m-d H:i:s", "2021-03-28 00:00:00"); $dtWithout = $dtWith; $invert = false; for ($i = 0; $i < 3; $i++) { print "\nRound {$i}:"; $dtWith = incrementWithSwitch($dtWith, $invert); $dtWithout = incrementWithoutSwitch($dtWithout, $invert); print "With switch: ". $dtWith->format(\DateTime::RFC3339); print " :: Without switch: ". $dtWithout->format(\DateTime::RFC3339); } Expected result: ---------------- Round 0:With switch: 2021-03-28T03:00:00+02:00 :: Without switch: 2021-03-28T03:00:00+02:00 Round 1:With switch: 2021-03-28T01:00:00+01:00 :: Without switch: 2021-03-28T01:00:00+02:00 Round 2:With switch: 2021-03-28T00:00:00+01:00 :: Without switch: 2021-03-28T00:00:00+02:00 --- Round 0:With switch: 2021-03-28T01:00:00+01:00 :: Without switch: 2021-03-28T01:00:00+01:00 Round 1:With switch: 2021-03-28T03:00:00+02:00 :: Without switch: 2021-03-28T03:00:00+02:00 Round 2:With switch: 2021-03-28T04:00:00+02:00 :: Without switch: 2021-03-28T04:00:00+02:00 Actual result: -------------- Round 0:With switch: 2021-03-28T03:00:00+02:00 :: Without switch: 2021-03-28T03:00:00+02:00 Round 1:With switch: 2021-03-28T01:00:00+01:00 :: Without switch: 2021-03-28T03:00:00+02:00 Round 2:With switch: 2021-03-28T00:00:00+01:00 :: Without switch: 2021-03-28T03:00:00+02:00 --- Round 0:With switch: 2021-03-28T01:00:00+01:00 :: Without switch: 2021-03-28T01:00:00+01:00 Round 1:With switch: 2021-03-28T03:00:00+02:00 :: Without switch: 2021-03-28T03:00:00+02:00 Round 2:With switch: 2021-03-28T04:00:00+02:00 :: Without switch: 2021-03-28T04:00:00+02:00 -- Edit bug report at https://bugs.php.net/bug.php?id=81072&edit=1 -- Fix committed: https://bugs.php.net/fix.php?id=81072&r=fixed Fixed in release: https://bugs.php.net/fix.php?id=81072&r=alreadyfixed Need backtrace: https://bugs.php.net/fix.php?id=81072&r=needtrace Need Reproduce Script: https://bugs.php.net/fix.php?id=81072&r=needscript Try newer version: https://bugs.php.net/fix.php?id=81072&r=oldversion Not developer issue: https://bugs.php.net/fix.php?id=81072&r=support Expected behavior: https://bugs.php.net/fix.php?id=81072&r=notwrong Not enough info: https://bugs.php.net/fix.php?id=81072&r=notenoughinfo Submitted twice: https://bugs.php.net/fix.php?id=81072&r=submittedtwice register_globals: https://bugs.php.net/fix.php?id=81072&r=globals PHP version support discontinued: https://bugs.php.net/fix.php?id=81072&r=phptooold Daylight Savings: https://bugs.php.net/fix.php?id=81072&r=dst IIS Stability: https://bugs.php.net/fix.php?id=81072&r=isapi Install GNU Sed: https://bugs.php.net/fix.php?id=81072&r=gnused Floating point limitations: https://bugs.php.net/fix.php?id=81072&r=float No Zend Extensions: https://bugs.php.net/fix.php?id=81072&r=nozend MySQL Configuration Error: https://bugs.php.net/fix.php?id=81072&r=mysqlcfg

« previous php.bugs (#233979) next »