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);