Wie vergleiche ich zwei DateTime-Objekte in PHP 5.2.8?


294

Wenn Sie sich die PHP-Dokumentation ansehen, DateTimescheinen die folgenden zwei Methoden des Objekts mein Problem zu lösen:

Beide Methoden sind im Dokument als in Version> = 5.3 verfügbar markiert (und es überrascht nicht, dass sie nicht vorhanden sind, wenn ich versuche, sie aufzurufen). Ich kann keine spezifische Dokumentation für 5.2.8 finden, daher bin ich mir nicht sicher, ob meine Version gleichwertige Methoden enthält. Ich habe das Problem gegoogelt und eine vielseitige Auswahl an Lösungen gefunden, von denen keine meine sehr einfachen Anforderungen erfüllt:

  • Wie vergleiche ich zwei DateTime-Objekte?
  • Wo finde ich das Dokument für frühere PHP-Versionen? Speziell Version 5.2.8?

Für einige Zusammenhänge habe ich den folgenden 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) 

Anscheinend gibt es keinen Vergleichsoperator für diesen Kerl.

Bearbeiten

Anscheinend waren meine Annahmen völlig falsch (danke Milen, dass er dies so effektiv illustriert hat). Es gibt einen Vergleichsoperator und es funktioniert gut, danke. Manchmal vermisse ich wirklich einen Compiler. Der Fehler befindet sich im obigen Code. Ich bin sicher, Sie werden ihn viel schneller finden als ich :).


1
Wenn Sie keinen Compiler haben, setzen Sie "error_reporting" auf "E_ALL" und Sie erhalten Hinweise wie "Hinweis: Undefinierte Variable: start_dt in ...".
Milen A. Radev

5
Bitte verwenden Sie auch HTML-Eigenschaften für Ihre Vars, sonst wird das $_POSTKätzchen getötet.
Clement Herreman

2
Und wo ist der Fehler? : p, ich mache es auch U_U. Danke im Voraus!
Castarco

2
@castarco Ich initialisiere $ st_dt, vergleiche aber mit einem nicht initialisierten $ start_dt. Überprüfen Sie Ihre Variablennamen und folgen Sie möglicherweise Milens Vorschlag und setzen Sie error_reporting auf E_ALL, um undefinierte Variablenwarnungen zu erhalten. :)
RedBlueThing

Antworten:


432

Folgendes scheint zu bestätigen, dass es Vergleichsoperatoren für die DateTime-Klasse gibt:

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
Danke Milen, es sieht so aus, als müsste ich nur meine falschen Annahmen entfernen und plötzlich wurde mir der grelle Fehler in meinem Code klar.
RedBlueThing

2
Hmm, das ist interessant. Vielleicht können wir irgendwann Operatoren in benutzerdefinierten Klassen überladen.
Ionuț G. Stan

1
Von php.net/manual/en/language.operators.comparison.php Integrierte Klassen können ihren eigenen Vergleich definieren, verschiedene Klassen sind unvergleichbar, dieselbe Klasse - vergleichen Sie Eigenschaften wie Arrays (PHP 4), PHP 5 hat seine eigene Erklärung
Saul

7
Achten Sie darauf, wenn Sie eine Datums- und Uhrzeitangabe ohne festgelegte Stunde mit einer festgelegten Uhrzeit vergleichen (Standardkonstruktor)
max4ever

1
TiMESPLiNTER, ich glaube, die Warnung ist, dass wenn Sie nur daran interessiert sind, Daten zu vergleichen, Sie möglicherweise die Tatsache übersehen, dass die Stunden unterschiedlich sind, und daher zwei DateTimes mit demselben Datum nicht als gleich verglichen werden, wenn Sie glauben, dass sie sollten. Sie können dies beheben, indem Sie die Zeitkomponenten des Objekts vor dem Vergleich explizit auf Null setzen.
Jason

52

Aus der offiziellen Dokumentation :

Ab PHP 5.2.2 können DateTime-Objekte mit Vergleichsoperatoren verglichen werden .

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

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

Für PHP-Versionen vor 5.2.2 (eigentlich für jede Version) können Sie diff verwenden .

$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
Ich finde diese Antwort am besten, da sie das Handbuch zitiert, anstatt nur das Verhalten zu überprüfen und davon auszugehen, dass das Ergebnis wie erwartet ist. SO ist kein Ort für Vermutungen. Bravo Roberto.
cprn

3
@roberto DateTime :: diff wurde nur in PHP 5.3
NeXuS

30

Sie können auch Sekunden der Epoche vergleichen:

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

Quelle: http://laughingmeme.org/2007/02/27/looking-at-php5s-datetime-and-datetimezone/ (ziemlich interessanter Artikel über DateTime)


16
Beachten Sie, dass dadurch formateine Zeichenfolge erstellt wird. Dies ist also ein Zeichenfolgenvergleich. Nach 1000000000 Epochen (ungefähr am 9. September 2001) ist dies kaum ein Problem. Wenn Sie sich jedoch mit Daten vor diesem Datum befassen müssen , können aufgrund unterschiedlicher Nummernlängen Probleme auftreten. Konvertieren Sie die Ergebnisse entweder in Zahlen (das Subtrahieren funktioniert auch) oder verwenden Sie ein wirklich sortierbares Format wie c.
MaxArt

1
@ MaxArt Könnten Sie bitte die Probleme aufgrund unterschiedlicher Stringlängen erläutern? Das Handbuch zu Zeichenfolgen in numerischen Kontexten: "Wenn die Zeichenfolge keine der Zeichen '.', 'E' oder 'E' enthält und der numerische Wert in ganzzahlige Typgrenzen (wie durch PHP_INT_MAX definiert) passt, wird die Zeichenfolge verwendet wird als Ganzzahl ausgewertet. In allen anderen Fällen wird es als float ausgewertet. " Zukünftige Daten (um 2038) können signierte 32-Bit-Ganzzahlen überlaufen lassen. Was ist jedoch das Problem bei älteren Daten?
Adrian Günter

1
@ AdrianGünter Das Problem ist, dass wir uns nicht in einem numerischen Kontext befinden würden, sondern uns mit Strings befassen würden . Numerisch, aber immer noch Zeichenfolgen. Es würde also ein Stringvergleich durchgeführt .
MaxArt


2
@ FrédéricMarchal Ja, ich habe später tatsächlich erfahren, dass mein vorheriger Kommentar tatsächlich falsch ist. PHP hat eine wirklich böse Art, diese Fälle zu behandeln. Keine andere Sprache (wie ich weiß) setzt Zahlen um, wenn Sie zwei Zeichenfolgen vergleichen müssen. Es macht Ihren Code wirklich fertig, wenn Sie tatsächlich einen lexikografischen Vergleich anstellen möchten.
MaxArt

20

Wenn Sie Datum und nicht Uhrzeit vergleichen möchten, können Sie Folgendes verwenden:

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

5
Sie können auch die Rücksetzzeit einstellen. $d1->setTime(0, 0, 0);
Athlan

3

Ab PHP 7.x können Sie Folgendes verwenden:

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

Zeitstempel hat einige Einschränkungen, vielleicht möchten Sie diese stackoverflow.com/a/7229760/2652018
Steel Brain

Gut zu wissen! Dies war nur für eine einfache Möglichkeit gedacht, Zeiten zu vergleichen.
Kyle Coots

-1

Dies kann Ihnen helfen.

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

Zeitstempel hat einige Einschränkungen, vielleicht möchten Sie diese stackoverflow.com/a/7229760/2652018
Steel Brain

@SteelBrain Glaubst du, dass die Zeitstempelbeschränkung über dem Code stört, der die gesamte aktuelle Datums- und Uhrzeit hat? Bitte lies den Code noch einmal. Es wird im Grunde genommen nach dem Typ $ expectedDate gesucht, der immer im aktuellen Monat sein wird. Ich denke nicht, dass wir hier in diesem Fall über die Zeitstempelbeschränkung nachdenken sollten.
Tarun Gupta

Ich weiß, aber es ist kein empfohlener Weg (ich habe nicht abgelehnt :-))
Steel Brain

Können Sie einen empfohlenen Weg vorschlagen?
Tarun Gupta

klar, $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";}Prost.
Steel Brain
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.