Bug #52480 [Com]: Incorrect difference using DateInterval

From: Date: Sat, 25 Jan 2014 19:24:55 +0000
Subject: Bug #52480 [Com]: Incorrect difference using DateInterval
References: 1  Groups: php.bugs 
Request: Send a blank email to php-bugs+get-184006@lists.php.net to get a copy of this message
Edit report at https://bugs.php.net/bug.php?id=52480&edit=1

 ID:                 52480
 Comment by:         kulakov74 at yandex dot ru
 Reported by:        alex dot joyce at staff dot comcen dot com dot au
 Summary:            Incorrect difference using DateInterval
 Status:             Assigned
 Type:               Bug
 Package:            Date/time related
 Operating System:   Debian 5.0.3
 PHP Version:        5.3.3
 Assigned To:        derick
 Block user comment: N
 Private report:     N

 New Comment:

I stumbled upon this seemingly wrong behaviour too, while studying the manual, and was all about to
add a confirming comment but finally realized the reason behind it. The explanation is that the
diff() method first converts its operands to UTC. In cases when the converion changes their months
the number of days in the month may change too. For ex. 2010-03-01/2010-07-29 in the very 1st
example, when in Europe/Copenhagen, actually converts to 2010-02-28 23:00:00/2010-07-28 23:00:00,
hence the difference 5 months 0 days. The conversion explains why the number of hours in the time
part matters and should be equal or greater than the timezone offset from UTC in order to avoid the
effect. 

Another consequence of the UTC conversion is that the function does not respect any DST shifts (it
that matters for you). Using strtotime() for the same dates and subtracting the timestamps might
yield a different result (+/-1 hour) if a DST switch is within the dates period. 

I also recommend using a DateTimeZone object for DateTime instead of changing the global TZ for all
date functions:

$oTZ=new DateTimeZone('Europe/Moscow');
$DT1=new DateTime('2010-03-01', $oTZ);


Previous Comments:
------------------------------------------------------------------------
[2014-01-17 13:54:42] jimmyraynor at gmail dot com

Ran into this issue with PHP 5.4.17 (cli) (built: Aug 25 2013 02:03:38) 
TZ: date.timezone => America/Santiago
Between dates 2013-09-08 and 2014-01-15
Using OS: Mac Os 10.9

------------------------------------------------------------------------
[2012-02-25 12:20:10] map at wafriv dot de

I've got the same problem with PHP 5.3.8 on Windows. Like petros at rufunka dot 
com said, there is a difference of 1 hour between Europe/Berlin and UTC.

object(DateTime)[1]
  public 'date' => string '2012-02-25 13:17:52' (length=19)
  public 'timezone_type' => int 3
  public 'timezone' => string 'Europe/Berlin' (length=13)
object(DateTime)[2]
  public 'date' => string '2010-08-07 07:01:25' (length=19)
  public 'timezone_type' => int 3
  public 'timezone' => string 'Europe/Berlin' (length=13)
object(DateInterval)[3]
  public 'y' => int 1
  public 'm' => int 6
  public 'd' => int 18
  public 'h' => int 6
  public 'i' => int 16
  public 's' => int 27
  public 'invert' => int 1
  public 'days' => int 567
object(DateTime)[4]
  public 'date' => string '2012-02-25 12:17:52' (length=19)
  public 'timezone_type' => int 3
  public 'timezone' => string 'UTC' (length=3)
object(DateTime)[1]
  public 'date' => string '2010-08-07 05:01:25' (length=19)
  public 'timezone_type' => int 3
  public 'timezone' => string 'UTC' (length=3)
object(DateInterval)[2]
  public 'y' => int 1
  public 'm' => int 6
  public 'd' => int 18
  public 'h' => int 7
  public 'i' => int 16
  public 's' => int 27
  public 'invert' => int 1
  public 'days' => int 567

------------------------------------------------------------------------
[2012-01-31 12:37:38] jan at jankramer dot eu

I think this bug is hasn't been fixed yet. 
Below is a reproduction on Ubuntu 11.10 with PHP 5.3.6. 

DateTime Object #1:
(
    [date] => 2011-12-01 00:00:00
    [timezone_type] => 3
    [timezone] => Europe/Amsterdam
)

DateTime Object #2:
(
    [date] => 2012-02-01 00:00:00
    [timezone_type] => 3
    [timezone] => Europe/Amsterdam
)

DateTime Object #3:
(
    [date] => 2011-12-01 12:00:00
    [timezone_type] => 3
    [timezone] => Europe/Amsterdam
)


DateTime Object #4:
(
    [date] => 2012-02-01 12:00:00
    [timezone_type] => 3
    [timezone] => Europe/Amsterdam
)

DateInterval Object #1 & #2
(
    [y] => 0
    [m] => 2
    [d] => 1
    [h] => 0
    [i] => 0
    [s] => 0
    [invert] => 0
    [days] => 62
)

DateInterval Object #3 & #4
(
    [y] => 0
    [m] => 2
    [d] => 0
    [h] => 0
    [i] => 0
    [s] => 0
    [invert] => 0
    [days] => 62
)

The difference in the 'd' attribute is very strange...

------------------------------------------------------------------------
[2011-06-13 10:51:00] petros at rufunka dot com

The problem lies between the last day of February and first day of March. 

At the following example:
$first = new DateTime('2011-03-01');
$second = new DateTime('2011-03-29');
$interval = $second->diff($first);

will get the wrong result.

If I set my timezone to Europe/Stockholm which is +1 GMT then if i set the $first = new
DateTime(’2011-03-01 00:59:00′); I still get the wrong result. However an hour value above
or equal to +1 ie $first = new DateTime(’2011-03-01 01:00:00′); will give the correct
example.

So if you are GMT + 2 you need to have a value above or equal to 2011-03-01 02:00:00.

A quick fix, as mentioned above, is to set your timezone to UTC:
date_default_timezone_set(‘UTC’);
and in this case you match the time with the needed in order to get correct results.

Another example with the opposite results is to set your timezone to:
date_default_timezone_set(‘America/Mexico_City’);
$first = new DateTime(’2011-02-28 22:01:00′);
$second = new DateTime(’2011-03-29 03:00:00′);
then the diff will think that you are in the same month.

------------------------------------------------------------------------
[2011-04-12 16:37:51] fischer at wild-east dot de

This happens only when setting a DateTime without the time part or a time below 02:00:00. At least
for the 'Europe/Berlin' timezone.

------------------------------------------------------------------------


The remainder of the comments for this report are too long. To view
the rest of the comments, please view the bug report online at

    https://bugs.php.net/bug.php?id=52480


-- 
Edit this bug report at https://bugs.php.net/bug.php?id=52480&edit=1


Thread (28 messages)

« previous php.bugs (#184006) next »