362

Having a look on the PHP documentation, the following two methods of the DateTime object would both seem to solve my problem:

Both these methods are marked in the doco as being available in version >= 5.3 (and, not surprisingly, if I try to call them I find they don't exist). I can't find any specific documentation for 5.2.8 so I am not sure if there are equivalent methods in my version. I have Googled the problem and found an eclectic range of solutions, none of which answer my very simple requirements:

  • How do I compare two DateTime objects?
  • Where can I find the doco for previous PHP versions? Specifically version 5.2.8?

For some context, I have the following code:

$st_dt = new DateTime(verifyParam ('start_date')); $end_dt = new DateTime(verifyParam ('end_date')); // is the end date more ancient than the start date? if ($end_dt < $start_dt) 

Apparently there is no comparison operator on this guy.

Edit

Apparently my assumptions were completely false (thanks Milen for illustrating this so effectively). There is a comparison operator and it works just fine thanks. Sometimes I really miss a compiler. The bug is in the code above, I am sure you will find it much faster than I did :).

4
  • 2
    Regarding the lack of compiler - set "error_reporting" to "E_ALL" and you'll get notices like "Notice: Undefined variable: start_dt in ...". Commented Jun 8, 2009 at 9:05
  • 5
    Also, please, use htmlentities on your $_POST vars, or kitten shall be killed. Commented Aug 30, 2010 at 8:56
  • 2
    And where is the error? :p , I'm doing it too U_U . Thanks in advance! Commented Nov 8, 2011 at 12:34
  • 2
    @castarco I initialise $st_dt , but I compare against an uninitialised $start_dt. Check your variable names and perhaps follow Milen's suggestion and set error_reporting to E_ALL to get undefined variable warnings. :) Commented Nov 8, 2011 at 22:20

8 Answers 8

516

The following seems to confirm that there are comparison operators for the DateTime class:

dev:~# php <?php date_default_timezone_set('Europe/London'); $d1 = new DateTime('2008-08-03 14:52:10'); $d2 = new DateTime('2008-01-03 11:11:10'); var_dump($d1 == $d2); var_dump($d1 > $d2); var_dump($d1 < $d2); ?> bool(false) bool(true) bool(false) dev:~# php -v PHP 5.2.6-1+lenny3 with Suhosin-Patch 0.9.6.2 (cli) (built: Apr 26 2009 20:09:03) Copyright (c) 1997-2008 The PHP Group Zend Engine v2.2.0, Copyright (c) 1998-2008 Zend Technologies dev:~# 
Sign up to request clarification or add additional context in comments.

10 Comments

Thanks Milen, looks like I just needed my false assumptions removed and suddenly the glaring bug in my code became obvious to me.
Hmm, this is interesting. Maybe at some point we'll be able to overload operators in user-defined classes.
From php.net/manual/en/language.operators.comparison.php Built-in classes can define its own comparison, different classes are uncomparable, same class - compare properties the same way as arrays (PHP 4), PHP 5 has its own explanation
watch out when comparing a datetime with no hour set and one with it set(default constructor)
TiMESPLiNTER, I believe the warning is that if you're only interested in comparing dates you might overlook the fact that the hours are different, and thus two DateTimes with the same date will not be compared as equal when you believe they should. You can remedy this by explicitly setting the time components of the object to zero before comparing them.
|
105

From the official documentation:

As of PHP 5.2.2, DateTime objects can be compared using comparison operators.

$date1 = new DateTime("now"); $date2 = new DateTime("tomorrow"); var_dump($date1 == $date2); // false var_dump($date1 < $date2); // true var_dump($date1 > $date2); // false 

For PHP versions before 5.2.2 (actually for any version), you can use diff.

$datetime1 = new DateTime('2009-10-11'); // 11 October 2013 $datetime2 = new DateTime('2009-10-13'); // 13 October 2013 $interval = $datetime1->diff($datetime2); echo $interval->format('%R%a days'); // +2 days 

2 Comments

I find this answer best since it quotes the manual instead of just checking the behavior and assuming the outcome is as expected. SO is not a place for guesswork. Bravo Roberto.
@roberto DateTime::diff has only been added in PHP 5.3
35

You can also compare epoch seconds :

$d1->format('U') < $d2->format('U') 

Source : http://laughingmeme.org/2007/02/27/looking-at-php5s-datetime-and-datetimezone/ (quite interesting article about DateTime)

7 Comments

Beware that format produces a string, so that's a string comparison. It's barely a problem after 1000000000 epoch time (roughly Sep 9th, 2001), but if you have to deal with dates before that, you may incur into problems due to different number lengths. Either convert the results to numbers (subtracting them works too), or use a truly sortable format like c.
@MaxArt could you please elaborate on the problems due to different string lengths? The manual, regarding strings in numeric contexts: "If the string does not contain any of the characters '.', 'e', or 'E' and the numeric value fits into integer type limits (as defined by PHP_INT_MAX), the string will be evaluated as an integer. In all other cases it will be evaluated as a float." Future dates (around 2038) can overflow signed 32-bit integers, but what's the issue with older dates?
@AdrianGünter The problem is that we wouldn't be in a numeric context, but we'd deal with strings. Numeric, but still strings. So a string comparison would be made.
@FrédéricMarchal Yes, I indeed learnt later that my previous comment is in fact false. PHP has a really wicked way to treat these cases, no other language (as I know of) casts to numbers when you have two strings to compare. It really screws your code if you actually want to make a lexicographical comparison.
|
25

If you want to compare dates and not time, you could use this:

$d1->format("Y-m-d") == $d2->format("Y-m-d") 

1 Comment

You can also set reset time. $d1->setTime(0, 0, 0);
2
$elapsed = '2592000'; // Time in the past $time_past = '2014-07-16 11:35:33'; $time_past = strtotime($time_past); // Add a month to that time $time_past = $time_past + $elapsed; // Time NOW $time_now = time(); // Check if its been a month since time past if($time_past > $time_now){ echo 'Hasnt been a month'; }else{ echo 'Been longer than a month'; } 

Comments

0

You mentioned DateTime::diff to compare two dates, you can use it to get a more precise value than just a boolean.

For example the number of days:

$date1 = new DateTime('2021-07-09'); $date2 = new DateTime('2020-10-21'); echo $date1->diff($date2)->format('%R%a days'); 

But you could also use an alias of DateTime::diff which is date_diff (PHP 5 >= 5.3.0, PHP 7, PHP 8)

$date1 = new DateTime('2021-07-09'); $date2 = new DateTime('2020-10-21'); echo date_diff($date1, $date2)->format('%R%a days'); 

Comments

-1

As of PHP 7.x, you can use the following:

$aDate = new \DateTime('@'.(time())); $bDate = new \DateTime('@'.(time() - 3600)); $aDate <=> $bDate; // => 1, `$aDate` is newer than `$bDate` 

2 Comments

This answer needs explanation of its unusual notation [backslash and '@'] and how it works [concat '@' with result of time(), ]
Answers need to include explanation of any unusual notation, like backslash, At-symbol, and spaceship operator. Code should include comments about how works, like: - concat '@' with result of time(), optionally subtracting one hour's worth of seconds - instantiate DateTime objects - compare DateTime objects, returning 0 if equal, or 1 if left value is greater, or -1 if right value is greater [Comment editing timeout window expired; cannot delete previous comment]
-2

This may help you.

$today = date("m-d-Y H:i:s"); $thisMonth =date("m"); $thisYear = date("y"); $expectedDate = ($thisMonth+1)."-08-$thisYear 23:58:00"; if (strtotime($expectedDate) > strtotime($today)) { echo "Expected date is greater then current date"; return ; } else { echo "Expected date is lesser then current date"; } 

4 Comments

@SteelBrain do you think that timestamp limitation bother above code which is having all current date time, Please read the code again, It basically check for the guy $expectedDate which will always be in the current month. I dont think so we should think about the timestamp limitation here in this case.
I know, but it's not a recommended way, (I didn't downvote :-) )
Can you suggest a recommended way.
sure, $today = new DateTime("now"); $time = DateTime::createFromFormat('d-m-Y',"26-October-1998"); if ($today > $time){echo "today is greater";}else{echo "other time is greater";} cheers.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.