| 
        php.net | support | documentation | report a bug | advanced search | search howto | statistics | random bug | login | 
  [2021-05-22 18:55 UTC] ph-bugs at allenjb dot me dot uk
 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 PatchesPull RequestsHistoryAllCommentsChangesGit/SVN commits             
             | 
    |||||||||||||||||||||||||||||||||||||
            
                 
                Copyright © 2001-2025 The PHP GroupAll rights reserved.  | 
        Last updated: Tue Nov 04 05:00:01 2025 UTC | 
> 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 So this about <https://3v4l.org/XWdf2>, right? If so, yes, that doesn't look right.Ran into the same issue, I have a very simple oneliner to reproduce it: ----- echo (new \DateTime('2022-03-13 03:00:00', new \DateTimeZone('America/Los_Angeles')))->modify('-5 minutes')->format('Y-m-d H:i:s'); ----- This becomes: 2022-03-13 03:55:00 Expected: 2022-03-13 01:55:00