Come faccio a confrontare due oggetti DateTime in PHP 5.2.8?


294

Dando un'occhiata alla documentazione di PHP, i seguenti due metodi DateTimedell'oggetto sembrano entrambi risolvere il mio problema:

Entrambi questi metodi sono contrassegnati nel doco come disponibili nella versione> = 5.3 (e, non a caso, se provo a chiamarli trovo che non esistano). Non riesco a trovare alcuna documentazione specifica per 5.2.8, quindi non sono sicuro che ci siano metodi equivalenti nella mia versione. Ho cercato su Google il problema e ho trovato una gamma eclettica di soluzioni, nessuna delle quali risponde ai miei requisiti molto semplici:

  • Come faccio a confrontare due oggetti DateTime?
  • Dove posso trovare il doco per le precedenti versioni di PHP? In particolare la versione 5.2.8?

Per alcuni contesti, ho il seguente codice:

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

Apparentemente non c'è nessun operatore di confronto su questo ragazzo.

modificare

Apparentemente i miei presupposti erano completamente falsi (grazie Milen per averlo illustrato in modo così efficace). C'è un operatore di confronto e funziona bene grazie. A volte mi manca davvero un compilatore. Il bug è nel codice sopra, sono sicuro che lo troverai molto più velocemente di me :).


1
Per quanto riguarda la mancanza di compilatore, imposta "error_reporting" su "E_ALL" e otterrai avvisi come "Avviso: variabile non definita: start_dt in ...".
Milen A. Radev,

5
Inoltre, per favore, usa htmlentities sui tuoi $_POSTvar, o il gattino deve essere ucciso.
Clemente Herreman,

2
E dov'è l'errore? : p, lo sto facendo anch'io U_U. Grazie in anticipo!
castarco,

2
@castarco Inizializzo $ st_dt, ma confronto con un $ start_dt non inizializzato. Controlla i nomi delle tue variabili e forse segui il suggerimento di Milen e imposta error_reporting su E_ALL per ottenere avvisi variabili non definiti. :)
RedBlueThing

Risposte:


432

Quanto segue sembra confermare che esistono operatori di confronto per 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
Grazie Milen, sembra che avessi solo bisogno di rimuovere i miei falsi presupposti e improvvisamente il bagliore evidente nel mio codice è diventato ovvio per me.
RedBlueThing

2
Hmm, questo è interessante. Forse a un certo punto saremo in grado di sovraccaricare gli operatori in classi definite dall'utente.
Ionuț G. Stan,

1
Da php.net/manual/en/language.operators.comparison.php Le classi integrate possono definire il proprio confronto, classi diverse sono incomparabili, stessa classe - confrontare le proprietà allo stesso modo degli array (PHP 4), PHP 5 ha il suo propria spiegazione
Saul

7
fare attenzione quando si confronta un datetime con nessuna ora impostata e uno con esso impostato (costruttore predefinito)
max4ever

1
TiMESPLiNTER, credo che l'avvertimento sia che se sei interessato solo a confrontare le date potresti trascurare il fatto che le ore sono diverse, e quindi due DateTimes con la stessa data non saranno confrontati come uguali quando ritieni che dovrebbero. È possibile rimediare impostando esplicitamente i componenti temporali dell'oggetto su zero prima di confrontarli.
Jason,

52

Dalla documentazione ufficiale :

A partire da PHP 5.2.2, gli oggetti DateTime possono essere confrontati usando operatori di confronto .

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

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

Per le versioni di PHP precedenti alla 5.2.2 (in realtà per qualsiasi versione), è possibile utilizzare 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
Trovo questa risposta migliore poiché cita il manuale invece di controllare il comportamento e supporre che il risultato sia come previsto. SO non è un luogo per congetture. Bravo Roberto.
cprn,

3
@roberto DateTime :: diff è stato aggiunto solo in PHP 5.3
NeXuS

30

Puoi anche confrontare i secondi di epoca:

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

Fonte: http://laughingmeme.org/2007/02/27/looking-at-php5s-datetime-and-datetimezone/ (articolo abbastanza interessante su DateTime)


16
Attenzione che formatproduce una stringa , quindi questo è un confronto tra stringhe. È appena un problema dopo 1000000000 di tempo (all'incirca il 9 settembre 2001), ma se devi affrontare date precedenti , potresti incorrere in problemi a causa della diversa lunghezza dei numeri. O converti i risultati in numeri (sottraendoli funziona anche) o usa un formato veramente ordinabile come c.
MaxArt,

1
@MaxArt potresti per favore approfondire i problemi dovuti alle diverse lunghezze delle stringhe? Il manuale, per quanto riguarda le stringhe in contesti numerici: "Se la stringa non contiene nessuno dei caratteri '.', 'E' o 'E' e il valore numerico si adatta ai limiti del tipo intero (come definito da PHP_INT_MAX), la stringa verrà valutato come un numero intero. In tutti gli altri casi verrà valutato come float. " Le date future (intorno al 2038) possono traboccare numeri interi con segno a 32 bit, ma qual è il problema con le date precedenti?
Adrian Günter,

1
@ AdrianGünter Il problema è che non saremmo in un contesto numerico, ma avremmo a che fare con le stringhe . Stringhe numeriche, ma comunque. Quindi verrebbe effettuato un confronto tra stringhe .
MaxArt


2
@ FrédéricMarchal Sì, ho appreso in seguito che il mio commento precedente è in realtà falso. PHP ha un modo davvero malvagio di trattare questi casi, nessun altro linguaggio (come so di) lancia ai numeri quando hai due stringhe da confrontare. Ti rovina davvero il codice se vuoi davvero fare un confronto lessicografico.
MaxArt,

20

Se si desidera confrontare le date e non l'ora, è possibile utilizzare questo:

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

5
È inoltre possibile impostare il tempo di ripristino. $d1->setTime(0, 0, 0);
Athlan,

3

A partire da PHP 7.x, puoi usare quanto segue:

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

il timestamp ha alcune limitazioni, potresti leggere questo stackoverflow.com/a/7229760/2652018
Steel Brain

Bello sapere! Questo era pensato solo per un modo semplice di confrontare i tempi.
Kyle Coots

-1

Questo può aiutarti.

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

il timestamp ha alcune limitazioni, potresti leggere questo stackoverflow.com/a/7229760/2652018
Steel Brain

@SteelBrain pensi che la limitazione del timestamp dia fastidio al di sopra del codice che sta avendo tutto l'ora della data corrente, per favore leggi di nuovo il codice, fondamentalmente controlla per l'uomo $ prevista Data che sarà sempre nel mese corrente. Non penso quindi dovremmo pensare alla limitazione di data e ora qui in questo caso.
Tarun Gupta,

Lo so, ma non è un modo consigliato, (non ho votato in basso :-))
Steel Brain

Puoi suggerire un modo consigliato.
Tarun Gupta,

certo, $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";}evviva.
Steel Brain,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.