php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #68474 DateTime comparison fails
Submitted: 2014-11-21 19:04 UTC Modified: 2015-04-19 23:15 UTC
Votes:5
Avg. Score:4.0 ± 0.9
Reproduced:3 of 4 (75.0%)
Same Version:1 (33.3%)
Same OS:1 (33.3%)
From: cwente at ip dot ulagos dot cl Assigned:
Status: Verified Package: Date/time related
PHP Version: 5.5.19 OS: Debian Linux 7.7
Private report: No CVE-ID: None
Have you experienced this issue?
Rate the importance of this bug to you:

 [2014-11-21 19:04 UTC] cwente at ip dot ulagos dot cl
Description:
------------
When creating a DateTime from the WTC representation and then copying the DateTimeZone the comparison (<,>,==) fails.

In the example script PHP will say that 
2014-11-21 18:00:00 ==
2014-11-21 15:00:00
both with DateTimeZone -03:00, which is clearly wrong.

Test script:
---------------
$a = new DateTime("2014-11-21 15:00:00", new DateTimeZone("America/Santiago"));
echo "------------------\nCopying \$b from W3C representation of \$a\n";
$b = new DateTime($a->format(DateTime::W3C));
compare($a, $b);
$a->add(new DateInterval("PT3H"));
echo "------------------\nAdd 3 hours to \$a\n";
compare($a, $b);
$a->setTimezone($b->getTimezone());
echo "------------------\nSet Timezone of \$a to Timezone of \$b\n";
compare($a, $b);
echo "------------------\nCompare Timestamps:\n";
compare($a->getTimestamp(), $b->getTimestamp());

function compare($a, $b) {
    var_dump($a);
    var_dump($b);
    echo ($a > $b ? '$a > $b' : ($a < $b ? '$a < $b' : ($a == $b ? '$a == $b' : 'undefined'))) . "\n";
}

Expected result:
----------------
The time in the future should be greater than the time in the past, if the timezone is the same.

Actual result:
--------------
------------------
Copying $b from W3C representation of $a
class DateTime#1 (3) {
  public $date =>
  string(26) "2014-11-21 15:00:00.000000"
  public $timezone_type =>
  int(3)
  public $timezone =>
  string(16) "America/Santiago"
}
class DateTime#2 (3) {
  public $date =>
  string(26) "2014-11-21 15:00:00.000000"
  public $timezone_type =>
  int(1)
  public $timezone =>
  string(6) "-03:00"
}
$a == $b
------------------
Add 3 hours to $a
class DateTime#1 (3) {
  public $date =>
  string(26) "2014-11-21 18:00:00.000000"
  public $timezone_type =>
  int(3)
  public $timezone =>
  string(16) "America/Santiago"
}
class DateTime#2 (3) {
  public $date =>
  string(26) "2014-11-21 15:00:00.000000"
  public $timezone_type =>
  int(1)
  public $timezone =>
  string(6) "-03:00"
}
$a > $b
------------------
Set Timezone of $a to Timezone of $b
class DateTime#1 (3) {
  public $date =>
  string(26) "2014-11-21 18:00:00.000000"
  public $timezone_type =>
  int(1)
  public $timezone =>
  string(6) "-03:00"
}
class DateTime#2 (3) {
  public $date =>
  string(26) "2014-11-21 15:00:00.000000"
  public $timezone_type =>
  int(1)
  public $timezone =>
  string(6) "-03:00"
}
$a == $b
------------------
Compare Timestamps:
int(1416603600)
int(1416592800)
$a > $b


Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2015-01-31 02:37 UTC] dana dot desrosiers at gmail dot com
I ran into this problem in PHP 5.6.3 as well.  This is what I think is happening:

The DateTime object has a timestamp property that is used to compare two DateTime objects using comparison operators (<, >, ==, etc.).  When the setTimezone() method is called, the timezone property is set, but the internal timestamp is never updated, so comparisons may be wrong.

Calling getTimestamp() or modify() after setTimezone() corrects the error.

This bug does not exist in 5.3.27.
 [2015-01-31 20:59 UTC] me at philsturgeon dot uk
Can you let me know if this test script looks right? 

https://github.com/philsturgeon/php-src/compare/bug68474?expand=1#diff-2a05f4a70189b96241223c2ea214ffc9R1

I'll try and get it fixed up if you can help me confirm the expected result.
 [2015-02-02 05:46 UTC] dana dot desrosiers at gmail dot com
The test description on Line 2 is not correct.  Looks like it was copied from another test.  

It looks like the EXPECT section shows the current behavior, including an illustration of the workaround.  I think its meant to show what should happen when the bug is fixed, right?  

I know this is modeled after the original bug reporter's example, but I think its more complicated than it needs to be to test the bug.  Here's a more simple illustration:

// Create two identical DateTime objects
$a = new DateTime("2015-02-01 00:00:00", new DateTimeZone("PST"));
$b = clone $a;
// They should be equal (and they are)
compare($a, $b);
// Now change the timezone to EST.
$b->setTimezone(new DateTimeZone("EST"));
//The actual timestamp should not change (it does not in PHP 5.4) so $a should still be equal to $b, but it will say $a > $b.
compare($a, $b);


The workaround:

$b->getTimestamp();
compare($a, $b);
// it will now correctly report "$a == $b".

Thanks for working on this.
 [2015-04-19 23:15 UTC] cmb@php.net
-Status: Open +Status: Verified
 [2015-04-19 23:15 UTC] cmb@php.net
Apparently, the behavior changed with PHP 5.5.10: <http://3v4l.org/dTOrf#v5430>. It might be related to fixing bug #45528.
 
PHP Copyright © 2001-2017 The PHP Group
All rights reserved.
Last updated: Sun Nov 19 01:31:42 2017 UTC