Comment comparer deux objets DateTime en PHP 5.2.8?


294

En jetant un œil à la documentation PHP, les deux méthodes suivantes de l' DateTimeobjet semblent toutes les deux résoudre mon problème:

Ces deux méthodes sont marquées dans le doco comme étant disponibles dans la version> = 5.3 (et, sans surprise, si j'essaye de les appeler je trouve qu'elles n'existent pas). Je ne trouve aucune documentation spécifique pour 5.2.8, donc je ne suis pas sûr qu'il existe des méthodes équivalentes dans ma version. J'ai recherché le problème sur Google et trouvé une gamme éclectique de solutions, dont aucune ne répond à mes exigences très simples:

  • Comment comparer deux objets DateTime?
  • Où puis-je trouver le doco pour les versions PHP précédentes? Plus précisément la version 5.2.8?

Pour un certain contexte, j'ai le code suivant:

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

Apparemment, il n'y a pas d'opérateur de comparaison sur ce type.

Éditer

Apparemment, mes hypothèses étaient complètement fausses (merci Milen d'avoir illustré cela si efficacement). Il y a un opérateur de comparaison et cela fonctionne très bien merci. Parfois, je manque vraiment un compilateur. Le bug est dans le code ci-dessus, je suis sûr que vous le trouverez beaucoup plus rapidement que moi :).


1
Concernant le manque de compilateur - définissez "error_reporting" sur "E_ALL" et vous obtiendrez des notifications comme "Notice: Variable non définie: start_dt dans ...".
Milen A. Radev, le

5
Veuillez également utiliser htmlentities sur vos $_POSTvars, sinon le chaton sera tué.
Clement Herreman

2
Et où est l'erreur? : p, je le fais aussi U_U. Merci d'avance!
castarco

2
@castarco J'initialise $ st_dt, mais je compare avec un $ start_dt non initialisé. Vérifiez vos noms de variable et suivez peut-être la suggestion de Milen et définissez error_reporting sur E_ALL pour obtenir des avertissements de variable non définis. :)
RedBlueThing

Réponses:


432

Ce qui suit semble confirmer qu'il existe des opérateurs de comparaison pour la classe 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:~#

7
Merci Milen, on dirait que je voulais juste que mes fausses hypothèses soient supprimées et tout à coup, le bug flagrant de mon code est devenu évident pour moi.
RedBlueThing

2
Hmm, c'est intéressant. Peut-être qu'à un moment donné, nous pourrons surcharger les opérateurs dans les classes définies par l'utilisateur.
Ionuț G. Stan

1
Depuis php.net/manual/en/language.operators.comparison.php Les classes intégrées peuvent définir sa propre comparaison, différentes classes sont incomparables, même classe - comparez les propriétés de la même manière que les tableaux (PHP 4), PHP 5 a ses propre explication
Saul

7
faites attention lorsque vous comparez un datetime sans heure définie et un avec lui défini (constructeur par défaut)
max4ever

1
TiMESPLiNTER, je pense que l'avertissement est que si vous ne souhaitez comparer les dates que vous pourriez ignorer le fait que les heures sont différentes, et donc deux DateTimes avec la même date ne seront pas comparés comme égaux quand vous pensez qu'ils devraient. Vous pouvez y remédier en définissant explicitement les composants temporels de l'objet sur zéro avant de les comparer.
Jason

52

De la documentation officielle :

Depuis PHP 5.2.2, les objets DateTime peuvent être comparés à l'aide d' opérateurs de comparaison .

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

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

Pour les versions PHP antérieures à 5.2.2 (en fait pour n'importe quelle version), vous pouvez utiliser 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

3
Je trouve cette réponse meilleure car elle cite le manuel au lieu de simplement vérifier le comportement et de supposer que le résultat est comme prévu. SO n'est pas un lieu de conjectures. Bravo Roberto.
cprn

3
@roberto DateTime :: diff n'a été ajouté qu'en PHP 5.3
NeXuS

30

Vous pouvez également comparer les secondes d'époque:

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

Source: http://laughingmeme.org/2007/02/27/looking-at-php5s-datetime-and-datetimezone/ (article assez intéressant sur DateTime)


16
Attention, cela formatproduit une chaîne , c'est donc une comparaison de chaînes. C'est à peine un problème après 1000000000 d'époque (environ le 9 septembre 2001), mais si vous devez faire face à des dates antérieures , vous risquez de rencontrer des problèmes en raison de différentes longueurs de numéros. Soit convertir les résultats en nombres (les soustraire fonctionne aussi), soit utiliser un format vraiment triable comme c.
MaxArt

1
@MaxArt pourriez-vous s'il vous plaît expliquer les problèmes dus aux différentes longueurs de chaîne? Le manuel, concernant les chaînes dans des contextes numériques: "Si la chaîne ne contient aucun des caractères". "," E "ou" E "et que la valeur numérique s'inscrit dans les limites de type entier (telles que définies par PHP_INT_MAX), la chaîne sera évalué comme un entier. Dans tous les autres cas, il sera évalué comme un flottant. " Les dates futures (vers 2038) peuvent dépasser les entiers signés 32 bits, mais quel est le problème avec les dates plus anciennes?
Adrian Günter du

1
@ AdrianGünter Le problème est que nous ne serions pas dans un contexte numérique, mais nous traiterions avec des chaînes . Numérique, mais toujours des chaînes. Une comparaison de chaînes serait donc effectuée.
MaxArt


2
@ FrédéricMarchal Oui, j'ai en effet appris plus tard que mon précédent commentaire est en fait faux. PHP a une façon vraiment méchante de traiter ces cas, aucun autre langage (à ma connaissance) ne convertit en nombres lorsque vous avez deux chaînes à comparer. Cela visse vraiment votre code si vous voulez réellement faire une comparaison lexicographique.
MaxArt

20

Si vous souhaitez comparer des dates et non des heures, vous pouvez utiliser ceci:

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

5
Vous pouvez également définir l'heure de réinitialisation. $d1->setTime(0, 0, 0);
Athlan

3

Depuis PHP 7.x, vous pouvez utiliser les éléments suivants:

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

$aDate <=> $bDate; // => 1, `$aDate` is newer than `$bDate`

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';
}

l'horodatage a quelques limitations, vous voudrez peut-être lire ce stackoverflow.com/a/7229760/2652018
Steel Brain

Bon à savoir! C'était juste destiné à un moyen simple de comparer les temps.
Kyle Coots

-1

Cela peut vous aider.

$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";
}

l'horodatage a quelques limitations, vous voudrez peut-être lire ce stackoverflow.com/a/7229760/2652018
Steel Brain

@SteelBrain pensez-vous que la limitation de l'horodatage dérange au-dessus du code qui a toute l'heure de la date actuelle, s'il vous plaît relisez le code, il vérifie essentiellement le gars $ attenduDate qui sera toujours dans le mois en cours. Je ne pense pas, nous devrions donc penser à la limitation d'horodatage ici dans ce cas.
Tarun Gupta

Je sais, mais ce n'est pas une méthode recommandée, (je n'ai pas dévalorisé :-))
Steel Brain

Pouvez-vous suggérer une méthode recommandée.
Tarun Gupta

bien sûr, $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";}bravo.
Steel Brain
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.