¿Cómo comparo dos objetos DateTime en PHP 5.2.8?

294

Al echar un vistazo a la documentación de PHP, los siguientes dos métodos del DateTimeobjeto parecen resolver mi problema:

Ambos métodos están marcados en el doco como disponibles en la versión> = 5.3 (y, como es lógico, si trato de llamarlos, encuentro que no existen). No puedo encontrar ninguna documentación específica para 5.2.8, así que no estoy seguro de si hay métodos equivalentes en mi versión. He buscado en Google el problema y ha encontrado una ecléctica variedad de soluciones, ninguna de las cuales responden a mis necesidades muy simples:

  • ¿Cómo comparo dos objetos DateTime?
  • ¿Dónde puedo encontrar el doco para versiones anteriores de PHP? Específicamente la versión 5.2.8?

Para algún contexto, tengo el siguiente código:

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

Aparentemente no hay operador de comparación en este tipo.

Editar

Aparentemente, mis suposiciones eran completamente falsas (gracias Milen por ilustrar esto tan efectivamente). Hay un operador de comparación y funciona bien, gracias. A veces realmente extraño un compilador. El error está en el código anterior, estoy seguro de que lo encontrará mucho más rápido que yo :).

RedBlueThing
fuente
1
Con respecto a la falta de compilador, configure "error_reporting" en "E_ALL" y recibirá avisos como "Aviso: Variable indefinida: start_dt en ...".
Milen A. Radev
55
Además, por favor, use htmlentities en sus $_POSTvars, o el gatito será asesinado.
Clement Herreman
2
¿Y dónde está el error? : p, yo también lo estoy haciendo U_U. ¡Gracias por adelantado!
castarco
2
@castarco Inicializo $ st_dt, pero lo comparo con un $ start_dt no inicializado. Verifique los nombres de sus variables y quizás siga la sugerencia de Milen y configure error_reporting en E_ALL para obtener advertencias de variables indefinidas. :)
RedBlueThing

Respuestas:

432

Lo siguiente parece confirmar que hay operadores de comparación para la clase DateTime:

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:~#
Milen A. Radev
fuente
77
Gracias Milen, parece que solo necesitaba eliminar mis suposiciones falsas y, de repente, el error evidente en mi código se hizo evidente para mí.
RedBlueThing
2
Hmm, esto es interesante. Quizás en algún momento podamos sobrecargar operadores en clases definidas por el usuario.
Ionuț G. Stan
1
Desde php.net/manual/en/language.operators.comparison.php Las clases incorporadas pueden definir su propia comparación, las diferentes clases son incomparables, la misma clase: compare las propiedades de la misma manera que las matrices (PHP 4), PHP 5 tiene su propia explicación
Saul
77
tenga cuidado al comparar una fecha y hora sin hora establecida y una con ella establecida (constructor predeterminado)
max4ever
1
TIEMPOSPLITER, creo que la advertencia es que si solo está interesado en comparar fechas, puede pasar por alto el hecho de que las horas son diferentes y, por lo tanto, dos DateTimes con la misma fecha no se compararán como iguales cuando cree que deberían hacerlo. Puede remediar esto estableciendo explícitamente los componentes de tiempo del objeto a cero antes de compararlos.
Jason
52

De la documentación oficial :

A partir de PHP 5.2.2, los objetos DateTime se pueden comparar utilizando operadores de comparación .

$date1 = new DateTime("now");
$date2 = new DateTime("tomorrow");

var_dump($date1 == $date2); // false
var_dump($date1 < $date2); // true
var_dump($date1 > $date2); // false

Para las versiones de PHP anteriores a 5.2.2 (en realidad para cualquier versión), puede usar 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
Roberto Alonso
fuente
3
Encuentro esta respuesta mejor ya que cita el manual en lugar de simplemente verificar el comportamiento y asumir que el resultado es el esperado. SO no es un lugar para adivinar. Bravo Roberto.
cprn
3
@roberto DateTime :: diff solo se ha agregado en PHP 5.3
NeXuS
30

También puede comparar los segundos de época:

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

Fuente: http://laughingmeme.org/2007/02/27/looking-at-php5s-datetime-and-datetimezone/ (artículo bastante interesante sobre DateTime)

Julien
fuente
16
Cuidado con que formatproduce una cadena , así que es una comparación de cadena. Apenas es un problema después del tiempo de 1000000000 (aproximadamente el 9 de septiembre de 2001), pero si tiene que lidiar con las fechas antes de eso, puede incurrir en problemas debido a diferentes longitudes de números. O convierta los resultados a números (restarlos también funciona), o use un formato verdaderamente ordenable como c.
MaxArt
1
@MaxArt, ¿podría explicar los problemas debido a las diferentes longitudes de cadena? El manual, con respecto a las cadenas en contextos numéricos: "Si la cadena no contiene ninguno de los caracteres '.', 'E' o 'E' y el valor numérico se ajusta a los límites de tipo entero (según lo definido por PHP_INT_MAX), la cadena se evaluará como un entero. En todos los demás casos se evaluará como flotante ". Las fechas futuras (alrededor de 2038) pueden desbordar enteros de 32 bits firmados, pero ¿cuál es el problema con las fechas anteriores?
Adrian Günter
1
@ AdrianGünter El problema es que no estaríamos en un contexto numérico, sino que trataríamos con cadenas . Numérico, pero aún cadenas. Entonces se haría una comparación de cadenas .
MaxArt
2
@ FrédéricMarchal Sí, más tarde supe que mi comentario anterior es falso. PHP tiene una forma realmente perversa de tratar estos casos, ningún otro lenguaje (como sé) arroja números cuando tienes dos cadenas para comparar. Realmente atornilla su código si realmente desea hacer una comparación lexicográfica.
MaxArt
20

Si desea comparar fechas y no horas, puede usar esto:

$d1->format("Y-m-d") == $d2->format("Y-m-d")
bla bla bla
fuente
55
También puede configurar el tiempo de reinicio. $d1->setTime(0, 0, 0);
Athlan
3

A partir de PHP 7.x, puede usar lo siguiente:

$aDate = new \DateTime('@'.(time()));
$bDate = new \DateTime('@'.(time() - 3600));

$aDate <=> $bDate; // => 1, `$aDate` is newer than `$bDate`
jens1o
fuente
0
$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';
}
Kyle Coots
fuente
la marca de tiempo tiene algunas limitaciones, es posible que desee leer este stackoverflow.com/a/7229760/2652018
Steel Brain el
¡Bueno saber! Esto fue solo para una manera simple de comparar tiempos.
Kyle Coots el
-1

Esto puede ayudarte.

$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";
}
Tarun Gupta
fuente
la marca de tiempo tiene algunas limitaciones, es posible que desee leer este stackoverflow.com/a/7229760/2652018
Steel Brain
@SteelBrain, ¿crees que la limitación de la marca de tiempo molesta al código anterior que tiene todas las fechas actuales? Por favor, lee el código nuevamente. No lo creo, así que deberíamos pensar en la limitación de marca de tiempo aquí en este caso.
Tarun Gupta
Lo sé, pero no es una forma recomendada, (no voté a favor :-))
Steel Brain
¿Puedes sugerir una forma recomendada?
Tarun Gupta
Claro, $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";}saludos.
Steel Brain