Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Are PHP DateInterval comparable like DateTime?

I discovered that a DateTime object in PHP can be compared to another as the ">" and "<" operators are overloaded.

Is it the same with DateInterval?

As I was trying to answer this question, I found something strange:

<?php   $today = new DateTime(); $release  = new DateTime('14-02-2012'); $building_time = new DateInterval('P15D'); var_dump($today->diff($release)); var_dump($building_time); var_dump($today->diff($release)>$building_time); var_dump($today->diff($release)<$building_time); if($today->diff($release) < $building_time){     echo 'oK'; }else{     echo 'Just a test'; } 

It always echoes "Just a test". The var_dump outputs are:

object(DateInterval)#4 (8) {   ["y"]=>   int(0)   ["m"]=>   int(0)   ["d"]=>   int(18)   ["h"]=>   int(16)   ["i"]=>   int(49)   ["s"]=>   int(19)   ["invert"]=>   int(1)   ["days"]=>   int(18) } object(DateInterval)#3 (8) {   ["y"]=>   int(0)   ["m"]=>   int(0)   ["d"]=>   int(15)   ["h"]=>   int(0)   ["i"]=>   int(0)   ["s"]=>   int(0)   ["invert"]=>   int(0)   ["days"]=>   bool(false) } bool(false) bool(true) 

When I try with a DateTime as "01-03-2012" everything works.

like image 419
artragis Avatar asked Mar 03 '12 16:03

artragis


2 Answers

In short, comparing of DateInterval objects is not currently supported by default (as of php 5.6).

As you already know, the DateTime Objects are comparable.

A way to achieve the desired result, is to subtract or add the DateInterval from a DateTime object and compare the two to determine the difference.

Example: https://3v4l.org/kjJPg

$buildDate = new DateTime('2012-02-15'); $releaseDate = clone $buildDate; $releaseDate->setDate(2012, 2, 14); $buildDate->add(new DateInterval('P15D'));  var_dump($releaseDate < $buildDate); //bool(true) 

Edit

As of the release of PHP 7.1 the results are different than with PHP 5.x, due to the added support for microseconds.

Example: https://3v4l.org/rCigC

$a = new \DateTime; $b = new \DateTime;  var_dump($a < $b); 

Results (7.1+):

bool(true) 

Results (5.x - 7.0.x, 7.1.3):

bool(false) 

To circumvent this behavior, it is recommended that you use clone to compare the DateTime objects instead.

Example: https://3v4l.org/CSpV8

$a = new \DateTime; $b = clone $a; var_dump($a < $b); 

Results (5.x - 7.x):

bool(false) 
like image 68
Will B. Avatar answered Sep 21 '22 14:09

Will B.


Looks like there was a related bug/feature request, not sure if that ever made it in the trunk. It's not documented (that I Can find) either way - so probably not safe to use.

That said, after some testing it seems that they can be compared, but only after they've been 'evaluated' in some way (doing a var dump changes the outcome). Here's my test/result:

<?php $int15 = new DateInterval('P15D'); $int20 = new DateInterval('P20D');  var_dump($int15 > $int20); //should be false; var_dump($int20 > $int15); //should be true;  var_dump($int15 < $int20); //should be true; var_dump($int20 < $int15); //should be false;  var_dump($int15); var_dump($int20);  var_dump($int15 > $int20); //should be false; var_dump($int20 > $int15); //should be true;  var_dump($int15 < $int20); //should be true; var_dump($int20 < $int15); //should be false;  $date = new DateTime(); $diff = $date->diff(new DateTime("+10 days"));  var_dump($int15 < $diff); //should be false; var_dump($diff < $int15); //should be true;  var_dump($int15 > $diff); //should be true; var_dump($diff > $int15); //should be false;  var_dump($diff);  var_dump($int15 < $diff); //should be false; var_dump($diff < $int15); //should be true;  var_dump($int15 > $diff); //should be true; var_dump($diff > $int15); //should be false; 

Result (I've omitted the full dumps of the interval objects):

 bool(false) bool(false) bool(false) bool(false) object(DateInterval)#1 (8) {...} object(DateInterval)#2 (8) {...} bool(false) bool(true) bool(true) bool(false)  bool(false) bool(true) bool(true) bool(false) object(DateInterval)#5 (8) {...} bool(false) bool(true) bool(true) bool(false) 
like image 31
Tim Lytle Avatar answered Sep 23 '22 14:09

Tim Lytle