You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
DatePeriod with 1 hour DateInterval misses hour on long DST day #8860
The following code attempts to loop over hours during the long day that has 1 extra hour because of the daylight saving switch in the location Europe/Amsterdam:
PT1H (P period) (T time) this can indicate an hour but in the transition period it is not simply the difference of 3600 seconds but the output of the local time, Europe/Amsterdam dayligth saving time ends on 2022-10-30 03:00:00 with backward 1 hour
From php 8.1.7 expected and correct 2022-10-30 01:00:00 1 1667084400 2022-10-30 02:00:00 1 1667088000 2022-10-30 03:00:00 0 1667095200
to learn more read the Documentation DateInterval which mentions which specification of http://en.wikipedia.org/wiki/Iso8601#Durations between the text you can also read Thus, "PT36H" could be used as well as "P1DT12H" for representing the same duration. But keep in mind that "PT36H" is not the same as "P1DT12H" when switching from or to Daylight saving time.
in php one hour or 3600 seconds is controlled by the date output, for example where you see 01:00:00 or 02:00:00 or 03:00:00 instead of the Unix timestamp, i.e. it works for its offset. From the dayligth saving time or standard time
DST ends at 03:00:00 for Europe/Amsterdam means offset +01:00 instead of +02:00
<?php// 2022-10-30 01:00:00 1 Europa/Amsterdam offset +02:00 1667084400 Unix Timestamp UTC 2022-10-29 23:00:00// 2022-10-30 02:00:00 1 Europa/Amsterdam offset +02:00:00 1667088000 Unix Timestamp UTC 2022-10-30 00:00:00//Valid 2022-10-30 03:00:00 0 Europa/Amsterdam offset +01:00 1667095200 Unix Timestamp UTC 2022-10-30 02:00:00//Not valid var_dump((new DateTime('2022-10-30 02:00:00', new DateTimeZone('Europe/Amsterdam')))->format('U'), '1667091600 => CET 2022-10-30 02:00:00 CEST 2022-10-30 03:00:00'); or 2022-10-30 03:00:00 1 Europa/Amsterdam offset +02:00 1667091600 Unix Timestamp UTC 2022-10-30 01:00:00?>
I am not sure what you are saying. This is key: But keep in mind that "PT36H" is not the same as "P1DT12H" when switching from or to Daylight saving time. But for PHP this is the case when switching from DST, so it doesn't follow the ISO principles of time.
The rest of your comment states that PHP currently doesn't work like that. I understand, that is why I reported it. I am somewhat surprised though that this has been a known issue since 2011. It isn't clear to me from the request for comments if there has been follow-up action?
Adding intervals like this is meant to add to the wall time. In that regard, what PHP 8.1.7 does is more correct than PHP 8.1.6. In 8.1.7 it adds 1 to the hour to make it go from 1 to 2, without being tipped up by the DST transition. The next addition makes it go from 2 to 3, but as 3:00 only exists as non-DST, the UTC offset than changes.
If you want to do every 3600 then your workaround is:
<?php
$utc = new DateTimeZone('UTC');
$timezone = new DateTimeZone('Europe/Amsterdam');
$interval = new DateInterval('PT1H');
$startDate = (new DateTime('2022-10-30 01:00:00', $timezone))->setTimezone($utc);
$endDate = (new DateTime('2022-10-30 04:00:00', $timezone))->setTimezone($utc);
$period = new DatePeriod($startDate, $interval, $endDate);
foreach ($period as $date) {
echo $date->setTimezone($timezone)->format('Y-m-d H:i:s I U') . PHP_EOL;
}
?>
Activity
hormus commentedon Jun 25, 2022
PT1H (P period) (T time) this can indicate an hour but in the transition period it is not simply the difference of 3600 seconds but the output of the local time, Europe/Amsterdam dayligth saving time ends on 2022-10-30 03:00:00 with backward 1 hour
From php 8.1.7 expected and correct
2022-10-30 01:00:00 1 1667084400 2022-10-30 02:00:00 1 1667088000 2022-10-30 03:00:00 0 1667095200zoispag commentedon Jun 25, 2022
I don't understand this.
If I change the interval to 3600 seconds, it is still producing the same output:
Looping over the
DatePeriodobject is skipping 3600 seconds, even if the interval is set to 3600 seconds.Are you suggesting that we should never rely on DateInterval for time zones with transitions?
hormus commentedon Jun 25, 2022
to learn more read the Documentation DateInterval which mentions which specification of http://en.wikipedia.org/wiki/Iso8601#Durations between the text you can also read Thus, "PT36H" could be used as well as "P1DT12H" for representing the same duration. But keep in mind that "PT36H" is not the same as "P1DT12H" when switching from or to Daylight saving time.
in php one hour or 3600 seconds is controlled by the date output, for example where you see 01:00:00 or 02:00:00 or 03:00:00 instead of the Unix timestamp, i.e. it works for its offset. From the dayligth saving time or standard time
DST ends at 03:00:00 for Europe/Amsterdam means offset +01:00 instead of +02:00
https://wiki.php.net/rfc/datetime_and_daylight_saving_time this specification indicates the backward transition when in doubt I open another issue. However there are only three dates and not 4 possible
RobertWeideKyos commentedon Jun 27, 2022
I am not sure what you are saying. This is key: But keep in mind that "PT36H" is not the same as "P1DT12H" when switching from or to Daylight saving time. But for PHP this is the case when switching from DST, so it doesn't follow the ISO principles of time.
The rest of your comment states that PHP currently doesn't work like that. I understand, that is why I reported it. I am somewhat surprised though that this has been a known issue since 2011. It isn't clear to me from the request for comments if there has been follow-up action?
derickr commentedon Jul 29, 2022
The behaviour with
PT1His now correct:Adding intervals like this is meant to add to the wall time. In that regard, what PHP 8.1.7 does is more correct than PHP 8.1.6. In 8.1.7 it adds
1to the hour to make it go from1to2, without being tipped up by the DST transition. The next addition makes it go from2to3, but as3:00only exists as non-DST, the UTC offset than changes.If you want to do every 3600 then your workaround is:
Which outputs:
savemetenminutes commentedon Dec 11, 2023
All this code for a simple task that should be intuitive? And furthermore this issue has been reported times over...