Skip to content

DateTime diff returns wrong sign on day count when using a timezone (Regression) #9880

Closed

Description

@neildaniels

Description

The following code:

https://3v4l.org/7biFY

<?php

ini_set('date.timezone', 'America/Los_Angeles');

$nowTime = new DateTime();
$nowTime->setTimestamp(1667416695);

$dateTime = new DateTime();
$dateTime->setTimestamp(1671904800);
$dateTime->setTimezone(new DateTimeZone('America/New_York'));

echo $dateTime->diff($nowTime)->format('%r%a');

Resulted in this output:

51

But I expected this output instead:

-51

This code works as expected prior to 8.1.10.

If you comment out the $dateTime->setTimezone(new DateTimeZone('America/New_York')); line, the code works as expected on all versions.

PHP Version

PHP 8.1.12

Operating System

Alpine 3.16

Activity

  1. cmb69 commented on Nov 3, 2022

    @cmb69
    Member

    Indeed, this look completely wrong.

  2. cmb69 commented on Nov 3, 2022

    @cmb69
    Member

    This might be a duplicate of #9866.

  3. ayanozturk commented on Nov 3, 2022

    @ayanozturk

    Similar difference in ->y value was introduced with PHP 8.1.10
    https://3v4l.org/Wiane
    It returns -1 instead of 0 when 2 dates with different timezones are compared.

  4. hormus commented on Nov 3, 2022

    @hormus
    <?php
    $utc = new DateTimeZone('UTC');
    $london = new DateTimeZone('Europe/London');
    
    $test1 = new \DateTime('2018-01-31', $utc);
    $test2 = new \DateTime('2018-03-31 00:00:00', $london);
    
    $dateDiff = $test2->diff($test1); // true absolute Should the interval be forced to be positive
    //$dateDiff = $test1->diff($test2);
    $bugs = array('y' => &$dateDiff->y, 'm' => &$dateDiff->m, 'd' => &$dateDiff->d, 'h' => &$dateDiff->h, 'invert' => &$dateDiff->invert, 'days' => &$dateDiff->days);
    $test3 = new \DateTime('+2 month ' . $test1->format('Y-m-d\\TH:i:s\\Z'));
    
    var_dump($test3->format('Y-m-d H:i:s +00:00'), $bugs);
    
    ?>

    php >= 8.1.10

    string(26) "2018-03-31 00:00:00 +00:00"
    array(6) {
      ["y"]=>
      int(-1)
      ["m"]=>
      int(10)
      ["d"]=>
      int(0)
      ["h"]=>
      int(1)
      ["invert"]=>
      int(0)
      ["days"]=>
      int(58)
    }
    

    php all
    If set $test2 = new \DateTime('2018-03-31 01:00:00', $london); and $test2->diff($test1) it's partial correct with inverter 1, if $test1->diff($test2) is correct

    php < 8.1.10

    string(26) "2018-03-31 00:00:00 +00:00"
    array(6) {
      ["y"]=>
      int(0)
      ["m"]=>
      int(1)
      ["d"]=>
      int(30)
      ["h"]=>
      int(23)
      ["invert"]=>
      int(1)
      ["days"]=>
      int(58)
    }
    

    if uncomment $dateDiff php < 8.1.10

    string(26) "2018-03-31 00:00:00 +00:00"
    array(6) {
      ["y"]=>
      int(0)
      ["m"]=>
      int(1)
      ["d"]=>
      int(27)
      ["h"]=>
      int(23)
      ["invert"]=>
      int(0)
      ["days"]=>
      int(58)
    }
    

    @cmb69 it's great bug exists for function diff (don't only duplicate)

    I am for restoring before creating same type timezone of php 8.1.10, adding a note in the manual for this use case otherwise the code needs improvement and I mean if different from same type it uses the same hacks that would be used with timezone type 3 Europe/Rome == Europe/Rome ... it is difficult to rewrite same type for this type of use.

  5. added a commit that references this issue on Nov 30, 2022
  6. derickr commented on Nov 30, 2022

    @derickr
    Member

    Now fixed, for PHP 8.1.14 and PHP 8.2.1.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions