php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #81263 Wrong result from DateTimeImmutable::diff
Submitted: 2021-07-15 21:32 UTC Modified: 2022-06-18 11:22 UTC
Votes:7
Avg. Score:4.1 ± 1.1
Reproduced:7 of 7 (100.0%)
Same Version:5 (71.4%)
Same OS:3 (42.9%)
From: mail at gh01 dot de Assigned: derick (profile)
Status: Assigned Package: Date/time related
PHP Version: master-Git-2021-07-15 (Git) OS:
Private report: No CVE-ID: None
View Add Comment Developer Edit
Welcome! If you don't have a Git account, you can't do anything here.
You can add a comment by following this link or if you reported this bug, you can edit this bug over here.
(description)
Block user comment
Status: Assign to:
Package:
Bug Type:
Summary:
From: mail at gh01 dot de
New email:
PHP Version: OS:

 

 [2021-07-15 21:32 UTC] mail at gh01 dot de
Description:
------------
PHP 8.0 (correct): https://3v4l.org/Wofuu#v8.0.8
PHP 8.1 (wrong): https://3v4l.org/Wofuu/rfc#vgit.master

Test script:
---------------
<?php

$dt1 = new DateTimeImmutable('2020-07-19 18:30:00', new DateTimeZone('Europe/Berlin'));
$dt2 = new DateTimeImmutable('2020-07-19 16:30:00', new DateTimeZone('UTC'));

print_r($dt1->diff($dt2));

Expected result:
----------------
DateInterval Object
(
    [y] => 0
    [m] => 0
    [d] => 0
    [h] => 0
    [i] => 0
    [s] => 0
    [f] => 0
    [weekday] => 0
    [weekday_behavior] => 0
    [first_last_day_of] => 0
    [invert] => 0
    [days] => 0
    [special_type] => 0
    [special_amount] => 0
    [have_weekday_relative] => 0
    [have_special_relative] => 0
)

Actual result:
--------------
DateInterval Object
(
    [y] => -1
    [m] => 11
    [d] => 29
    [h] => 24
    [i] => 0
    [s] => 0
    [f] => 0
    [weekday] => 0
    [weekday_behavior] => 0
    [first_last_day_of] => 0
    [invert] => 0
    [days] => 0
    [special_type] => 0
    [special_amount] => 0
    [have_weekday_relative] => 0
    [have_special_relative] => 0
)

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2021-08-08 11:18 UTC] derick@php.net
-Status: Open +Status: Duplicate
 [2021-08-08 11:18 UTC] derick@php.net
Duplicate of #81273
 [2021-10-07 22:36 UTC] mail at gh01 dot de
This issue still exists in current master: https://3v4l.org/f1fai/rfc#vgitmaster
 [2021-10-21 13:16 UTC] sjon@php.net
-Status: Duplicate +Status: Assigned -Assigned To: +Assigned To: derick
 [2021-10-21 13:16 UTC] sjon@php.net
while the related https://3v4l.org/8g4NB seems fixed, this issue remains
 [2021-10-21 13:23 UTC] cmb@php.net
This appears to be related to bug #81458.
 [2022-03-22 21:52 UTC] matthew at komputerwiz dot net
I pulled the latest source, compiled it, and ran the following example while in GDB:

    <?php
    $dFmt = \DateTimeInterface::ISO8601;
    $iFmt = '%R[%yy %mM %dd %hh %im %ss]';

    // creates new DateTime for the current timezone (UTC-5 in my case)
    $exp = new \DateTime('+3600 seconds', new \DateTimeZone('-5')); 
    echo 'expires: '.$exp->format($dFmt)."\n";

    $gen = $exp->getTimestamp() - 3600;

    // creates new DateTime in UTC
    $genTime = \DateTime::createFromFormat('U', (string) $gen);
    echo 'created: '.$genTime->format($dFmt)."\n";

    $ival = $exp->diff($genTime);
    echo 'interval: '.$ival->format($iFmt)."\n";

The expected interval output should be '-[0y 0M 0d 1h 0m 0s]', but is instead '-[-1y 11M 31d 1h 0m 0s]'.

The problem seems to start around timelib.c:90, during the early relative normalization step. Just prior to this point, the `rt` struct contains:

    {y:0, m:0, d:0, h:-4, i:0, s:0, ...}

The normalization step eliminates out-of-range negative values by "borrowing" from larger date units. After this point, `rt` contains:

    {y:-1, m:11, d:30, h:20, i:0, s:0, ...}

When this is corrected for timezone offset (h += 5) and normalized again, it leads to the unexpected output above.

Perhaps the issue stems from normalizing prior to correcting for time zone offset. If the timezone offset had been added prior to normalization, the "hours" field would have been in range.
 [2022-06-18 11:22 UTC] derick@php.net
Fixed in third party library: https://github.com/derickr/timelib/compare/php-81263?expand=1 — which means it will make it into PHP once this library gets merged again.
 
PHP Copyright © 2001-2022 The PHP Group
All rights reserved.
Last updated: Wed Jun 29 01:05:46 2022 UTC