Bug #52480 [Com]: Incorrect difference using DateInterval

From: Date: Wed, 19 Nov 2014 10:00:55 +0000
Subject: Bug #52480 [Com]: Incorrect difference using DateInterval
References: 1  Groups: php.bugs 
Request: Send a blank email to php-bugs+get-188675@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: ilantipov at gmail dot com 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: Had the same issue diff between 01-04-2014 and 01-07-2014 : DateTime Object ( [date] => 2014-04-01 00:00:00.000000 [timezone_type] => 3 [timezone] => Europe/Moscow ) DateTime Object ( [date] => 2014-07-01 00:00:00.000000 [timezone_type] => 3 [timezone] => Europe/Moscow ) DateInterval Object ( [y] => 0 [m] => 2 [d] => 30 [h] => 0 [i] => 0 [s] => 0 [weekday] => 0 [weekday_behavior] => 0 [first_last_day_of] => 0 [invert] => 1 [days] => 91 [special_type] => 0 [special_amount] => 0 [have_weekday_relative] => 0 [have_special_relative] => 0 ) The right interval is 3 month. Not 2 month 30 days. Both dates have same timezone. If I add date_default_timezone_set('UTC') before diff - everything works fine; Previous Comments: ------------------------------------------------------------------------ [2014-01-25 19:24:54] kulakov74 at yandex dot ru 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); ------------------------------------------------------------------------ [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. ------------------------------------------------------------------------ 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

« previous php.bugs (#188675) next »