Bug #52480 [Asn->Csd]: Incorrect difference using DateInterval
| From: | heiglandreas@php.net | Date: | Sun, 19 Mar 2017 09:58:47 +0000 |
| Subject: | Bug #52480 [Asn->Csd]: Incorrect difference using DateInterval | ||
| References: | 1 | Groups: | php.bugs |
| Request: | Send a blank email to php-bugs+get-207932@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
Updated by: heiglandreas@php.net
Reported by: alex dot joyce at staff dot comcen dot com dot au
Summary: Incorrect difference using DateInterval
-Status: Assigned
+Status: Closed
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:
This seems to be fixed in supported versions of PHP. Therefore I'm closing this issue.
php > $date_start = new DateTime('2010-03-01');
php > $date_end = new DateTime('2010-07-29');
php >
php > $interval = $date_start->diff($date_end);
php >
php > print_r($interval);
DateInterval Object
(
[y] => 0
[m] => 4
[d] => 28
[h] => 0
[i] => 0
[s] => 0
[f] => 0
[weekday] => 0
[weekday_behavior] => 0
[first_last_day_of] => 0
[invert] => 0
[days] => 150
[special_type] => 0
[special_amount] => 0
[have_weekday_relative] => 0
[have_special_relative] => 0
)
Previous Comments:
------------------------------------------------------------------------
[2016-11-23 07:14:51] lebeker at gmail dot com
Still got a problems:
(new DateTime('2016-10-01'))->diff((new DateTime('2016-10-31'))) // 1 month
(new DateTime('2016-11-01'))->diff((new DateTime('2016-11-30'))) // 29 days
either first should be 30 days, or the second one 1 month
(new DateTime('2016-11-01'))->diff((new DateTime('2016-12-01'))) // 30 days
but that's definitely 1 whole month
and what's more interesting
(new DateTime('2016-11-01'))->diff((new DateTime('2016-11-31'))) // 30 days
but there is no such date as '2016-11-31', but that's probably another bug.
PHP 7.0.8-0ubuntu0.16.04.3
------------------------------------------------------------------------
[2016-02-12 01:56:26] pinballfan at outlook dot com
After trying Marcel's code I got the same 'problem' on PHP 5.6 on a 64bit Windows 10
machine. However unexpected the result, I believe it is consistent with how PHP's datetime
rounds dates around. Using this example:
$date1 = new DateTime('2011-08-31T00:00:00Z');
$date2 = new DateTime('2012-03-01T00:00:00Z');
$interval = $date1->diff($date2);
var_dump($interval);
$interval->m = 5
$interval->d = 30
The expectation might be 6 months and 1 day
What I'm guessing might be happening is that PHP starts adding 1 month like so:
2011-08-31 = starting date
2011-09-31 = starting date + 1 month (but there is no such thing as sept 31!)
2011-10-01 = date now wraps around to 2011-10-01 since
2011-09-31 doesn't exist
2011-11-01 = + 1 month (2 total)
2011-12-01 = + 1 month (3 total)
2012-01-01 = + 1 month (4 total)
2012-02-01 = + 1 month (5 total)
2012-03-01 = When diff'ing PHP does NOT include the final date maybe like DatePeriod.
So that could be how it arrived at 5m and 30d
------------------------------------------------------------------------
[2015-01-12 09:43:52] marcel at berteler dot co dot za
I experience the same issue where the month is incorrectly calculated:
$Dob = new DateTime();
$Dob->setDate(2011, 8, 31);
$Dob->setTime(0,0,0);
$VisitDate = new DateTime();
$VisitDate->setDate(2012, 03, 01);
$VisitDate->setTime(0,0,0);
$interval = $Dob->diff($VisitDate);
echo $interval->m;
echo $interval->d;
Should return 6 & 1 but returns 5 & 30.
Changing the timezones still returns unexpected results:
$Dob = new DateTime();
$Dob->setTimezone(new DateTimeZone('UTC'));
$Dob->setDate(2011, 8, 30);
$Dob->setTime(0,0,0);
$VisitDate = new DateTime();
$VisitDate->setTimezone(new DateTimeZone('UTC'));
$VisitDate->setDate(2012, 2, 1);
$VisitDate->setTime(0,0,0);
$interval = $Dob->diff($VisitDate);
echo $interval->m; (returns 5)
echo $interval->d; (return 2)
2011-08-30 to 2012-03-01 return 6 months and 0 days.
Tried it in on both a Linux and Windows server and same result.
------------------------------------------------------------------------
[2014-11-19 10:00:52] ilantipov at gmail dot com
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;
------------------------------------------------------------------------
[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);
------------------------------------------------------------------------
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