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: Closed Package: Date/time related
PHP Version: master-Git-2021-07-15 (Git) OS:
Private report: No CVE-ID: None
 [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

Pull Requests

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.
 [2022-07-21 11:32 UTC] git@php.net
Automatic comment on behalf of derickr
Revision: https://github.com/php/php-src/commit/37d460b64a07888d45a72440f63880421f80d61e
Log: Fixed #81263: Wrong result from DateTimeImmutable::diff
 [2022-07-21 11:32 UTC] git@php.net
-Status: Assigned +Status: Closed
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Wed Nov 13 06:01:32 2024 UTC