php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #80913 DateTime(Immutable)::sub around DST yield incorrect time
Submitted: 2021-03-29 07:43 UTC Modified: 2021-04-06 19:57 UTC
Votes:1
Avg. Score:4.0 ± 0.0
Reproduced:1 of 1 (100.0%)
Same Version:1 (100.0%)
Same OS:1 (100.0%)
From: acm at tweakers dot net Assigned: derick (profile)
Status: Closed Package: Date/time related
PHP Version: 7.4 OS: all
Private report: No CVE-ID: None
View Developer Edit
Welcome! If you don't have a Git account, you can't do anything here.
If you reported this bug, you can edit this bug over here.
(description)
Block user comment
Status: Assign to:
Package:
Bug Type:
Summary:
From: acm at tweakers dot net
New email:
PHP Version: OS:

 

 [2021-03-29 07:43 UTC] acm at tweakers dot net
Description:
------------
DateTimeImmutable and DateTime with a time like '2021-03-28 03:00:00' in 'Europe/Amsterdam' (i.e. the moment of the DST-transition) will give the wrong time when substracting less than an hour. 

The same goes for all times that will give a result within an hour from 03:00+02:00.

I.e. when substracting 30 minutes, you get the same time as when _adding_ (+60-30 = ) 30 minutes.

And the same when using DateTimeImmutable. The before-output should be 01:30+01:00.

https://3v4l.org/ZZjvq (DateTimeImmutable)
https://3v4l.org/v3u2v (DateTime)

Btw substracting 60 minutes gives the exact same time again (03:00:00+02:00), while substracting 61 minutes correctly gives "2021-03-28T00:59:00+01:00".

Test script:
---------------
$date = new DateTime('2021-03-28 03:00:00', new DateTimeZone('Europe/Amsterdam'));
$_30mbefore = (clone $date)->sub(new DateInterval('PT30M'));
$_30mafter = (clone $date)->add(new DateInterval('PT30M'));

var_dump($date->format(DATE_ATOM));
var_dump($_30mbefore->format(DATE_ATOM));
var_dump($_30mafter->format(DATE_ATOM));



Expected result:
----------------
string(25) "2021-03-28T03:00:00+02:00"
string(25) "2021-03-28T01:30:00+01:00" (correct)
string(25) "2021-03-28T03:30:00+02:00"

Actual result:
--------------
string(25) "2021-03-28T03:00:00+02:00"
string(25) "2021-03-28T03:30:00+02:00" (incorrect)
string(25) "2021-03-28T03:30:00+02:00"

Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2021-03-29 16:00 UTC] cmb@php.net
-Status: Open +Status: Verified
 [2021-03-29 16:00 UTC] cmb@php.net
This affects older PHP versions as well[1].  Interestingly, there
is some code which is supposed to cater to that[2], but it is not
executed since t->dst==1.

[1] <https://3v4l.org/KKHlK>
[2] <https://github.com/php/php-src/blob/php-7.4.16/ext/date/lib/interval.c#L126>
 [2021-03-29 16:16 UTC] cmb@php.net
-PHP Version: 8.0.3 +PHP Version: 7.4
 [2021-03-31 16:34 UTC] cmb@php.net
This appears to be related to bug #60960, and might even have the
same root cause.
 [2021-03-31 17:38 UTC] cmb@php.net
Appears to be related to bug #73460 as well.
 [2021-04-06 19:57 UTC] derick@php.net
-Status: Verified +Status: Closed -Assigned To: +Assigned To: derick
 [2021-04-06 19:57 UTC] derick@php.net
The fix for this bug has been committed.
If you are still experiencing this bug, try to check out latest source from https://github.com/php/php-src and re-test.
Thank you for the report, and for helping us make PHP better.

Fixed for PHP 8.1.
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Thu Dec 05 16:01:30 2024 UTC