skip to Main Content

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.

3

Answers


  1. You seem to have hit a bug in PHP 7.3.11 that wasn’t there in the older version used by PhpFiddle. It’s also fixed the latest stable version, 7.4.11, so you should just upgrade your local PHP.

    (I notice that 7.3.11 is what ships with MacOS; if you’re on a Mac, you can install a newer PHP with Homebrew.)

    Login or Signup to reply.
  2. 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);       
    
    Login or Signup to reply.
  3. Yes, this is a bug and is related to your server time zone. You can use this workaround:

       $startDate = date_create('2019-11-01 UTC');
       $endDate = date_create('2019-12-01 UTC');
           
       $interval = date_diff($startDate, $endDate);
        
       echo $interval->m; //1     
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search