It’s probably just me being dumb, but …
<?php $startDate = date_create('2019-11-01'); $endDate = date_create('2019-12-01'); $interval = date_diff($startDate, $endDate); var_dump($interval); ?>
in PHPfiddle gives (as expected):
object(DateInterval)#3 (15)
{ [“y”]=> int(0)
[“m”]=> int(1) <=== this is what gives me problems on my local machine
[“d”]=> int(0)
[“h”]=> int(0)
[“i”]=> int(0)
[“s”]=> int(0)
[“weekday”]=> int(0)
[“weekday_behavior”]=> int(0)
[“first_last_day_of”]=> int(0)
[“invert”]=> int(0)
[“days”]=> int(30)
[“special_type”]=> int(0)
[“special_amount”]=> int(0)
[“have_weekday_relative”]=> int(0)
[“have_special_relative”]=> int(0) }
Check out the value of m
, which is number of months.
However, on my local machine, the same code gives:
class DateInterval#4 (16) { public $y => int(0) public $m => int(0) <====== why ??!! public $d => int(30) public $h => int(0) public $i => int(0) public $s => int(0) public $f => double(0) public $weekday => int(0) public $weekday_behavior => int(0) public $first_last_day_of => int(0) public $invert => int(0) public $days => int(30) public $special_type => int(0) public $special_amount => int(0) public $have_weekday_relative => int(0) public $have_special_relative => int(0) }
OK, I will concede that is is 30 days, but the answer that I was looking for was 1 month, and $interval->m
is zer0.
What am I missing? I don’t know what version of PHP the PHPfiddle web site uses, but I am using 7.3.11 locally.
Advertisement
Answer
Probably the difference is in the timezone.
try this:
<?php date_default_timezone_set('UTC'); $startDate = date_create('2019-11-01'); $endDate = date_create('2019-12-01'); $interval = date_diff($startDate, $endDate); var_dump($interval); /* object(DateInterval)#3 (16) { ["y"]=> int(0) ["m"]=> int(1) ... */
also try this:
<?php $startDate = date_create('2019-11-01 23:00'); $endDate = date_create('2019-12-01 23:00'); $interval = date_diff($startDate, $endDate); var_dump($interval); /* outputs the same ["m"]=> int(1) as above */
Probably date_diff looking for a difference between UTC timestamp and you have the default timezone on your PHP set to some positive value.
Let’s say you have some default timezone which is UTC+02:00 therefore
date_create('2019-11-01')
actually makes a date 2019-10-31 22:00:00 (UTC)
and date_create('2019-12-01')
actually makes a date 2019-11-30 22:00:00 (UTC)
now you can see they have no whole month difference.
But you can catch another funny effect:
<?php //assuming your timezone is UTC+something $startDate = date_create('2019-10-31'); // creates a date 2019-10-30 XX:00 UTC $endDate = date_create('2019-12-01'); // creates a date 2019-11-30 XX:00 UTC $interval = date_diff($startDate, $endDate); var_dump($interval); /* object(DateInterval)#3 (16) { ["y"]=> int(0) ["m"]=> int(1) sic(!) ["d"]=> int(0) sic(!) */
Also you may have unexpected result if your timezone has the daylight saving.
<?php // Germany has the daylight saving shift at last Sunday of March and October. date_default_timezone_set('Europe/Berlin'); $startDate = date_create('2020-03-28 03:00'); $endDate = date_create('2020-03-29 02:00'); $interval = date_diff($startDate, $endDate); var_dump($interval); // ["d"]=> int(1) ["h"]=> int(0) $startDate = date_create('2020-03-28 03:00'); $endDate = date_create('2020-03-29 03:00'); $interval = date_diff($startDate, $endDate); var_dump($interval); // ["d"]=> int(1) ["h"]=> int(0) $startDate = date_create('2020-03-28 03:00'); $endDate = date_create('2020-03-28 03:00'); // the same $endDate->modify('+23 hour'); $interval = date_diff($startDate, $endDate); var_dump($interval); // ["d"]=> int(1) ["h"]=> int(0)
PHPFiddle has the default timezone set to UTC, therefore it gives one month difference by default.
To avoid that, just perform all date calculations in UTC from the beginning:
<?php $timeZone = new DateTimeZone('UTC'); $startDate = new DateTime('2019-10-31', $timeZone); $endDate = new DateTime('2019-12-01', $timeZone); $interval = date_diff($startDate, $endDate); var_dump($interval);