2015-07-31 3 views
6

Ich habe ein Skript, das den aktuellen und im letzten Monat in PHP wie so bekommt:Warum funktioniert PHP Datum ('m', strtotime ('- 1 Monate')) nicht richtig für heute? 31.07

$currentMonth = date('m'); 
//Expected:07 
//Result:07 
$lastMonth = date('m', strtotime('-1 months')); 
//Expected:06 
//Result:07 

Heute geschieht das 31 oder am Ende des Monats Juli zu sein. Ist dieses Ergebnis von PHP zu erwarten?

Wenn -31 Tage mit dem Ergebnis wie erwartet:

$lastMonth = date('m', strtotime('-31 days')); 
//Expected:06 
//Result:06 
+0

Monat-Mathe ist immer riskant. Was ist ein Monat? "heute in ($ curmonth-1)", was passiert, wenn es der 31. März ist, möchtest du den 31. Februar oder den 28. Februar? Februar 29? –

+1

Sieht so aus, als wären das nicht die einzigen Tage, an denen '-1 Monate' Pause machen: http://codepad.viper-7.com/E4gP0W Der 31. eines Monats überrascht mich nicht, aber der 29. und 30. März tun es . –

+1

Immer erstaunt, wenn ich jemanden finde, der immer noch nicht https://github.com/briannesbitt/Carbon benutzt, um Daten in PHP zu machen. – ceejayoz

Antwort

2

Hier ein cleaner test case ist, das nicht abläuft:

<?php 
$origin = mktime(18, 0, 0, 7, 31, 2015); 
var_dump(date('r', $origin), date('r', strtotime('-1 months', $origin))); 
string(31) "Fri, 31 Jul 2015 18:00:00 +0200" 
string(31) "Wed, 01 Jul 2015 18:00:00 +0200" 

Ich bin mir ziemlich sicher, dass es sich um ein Dokumentationsproblem handelt, weil das Handbuch dies eindeutig angibt (Hervorhebung von mir):

Relative Monat Werte berechnet bezogen auf die Länge der Monate , die sie durchlaufen. Ein Beispiel wäre "+2 Monate 2011-11-30", welches "2012-01-30" produzieren würde. Dies liegt daran, dass der November 30 Tage lang ist und der Dezember 31 Tage lang ist, was insgesamt 61 Tage zu führt.

... und es ist falsch.

PHP-Bug-Tracker hat tons of dupes darüber. Sie sind alle geschlossen als kein Fehler. Hier ist eine relevante comment from 2009, die es erklärt:

Ich stimme zu, dass dies ein lästiges Verhalten ist.

Auch die Implementierung ist problematisch. Grundsätzlich Wenn Sie '+1 Monat' verwenden dauert es die Monatsnummer, fügt 1 hinzu und analysiert das Ergebnis als neues Datum.

Wenn Sie '+1 Monat' am ersten des Monats verwenden, wird das Datum auf das nächste erste des Monats festgelegt.

Dieses Verhalten vermittelt den Eindruck, dass php die Länge von pro Monat berücksichtigt, was nicht stimmt.

Aber wenn Sie ‚1 Monat‘ am letzten Tag eines Monats verwenden, ist das Ergebnis unerwarteten wie 2009-05-31 2009.06.31 wird, das ein ungültiges Datum und dann interpretiert als 2009-07-01.

Diese sollte mindestens in der Dokumentation erwähnt werden.

-1

Es gibt "s" mehr im Monat. Es sollte so aussehen:

$lastMonth = date('m', strtotime('-1 month')); 
+5

macht keinen Unterschied. PHP ist kein Grammatik-Nazi und '1 Monate' und' 1 Monat' sind soweit identisch. –

+1

Ah ja in Ordnung ... Soll ich die Antwort löschen? – lisztomania

+1

Tatsächlich ist das Extra 's' erlaubt/optional. Die [Dokumentation] (http://php.net/manual/en/datetime.formats.relative.php) bestätigt das. – axiac

2

Sie auf diese Weise

$d = new DateTime(); 
$currentMonth = $d->format('m'); 
//Expected:07 
//Result:07 
print $currentMonth; 

$d->modify('first day of previous month'); 
print "<br/>"; 
$lastMonth = $d->format('m'); 
//Expected:06 
//Result:06 
print $lastMonth; 

DEMO tun können: http://codepad.viper-7.com/kokWi8

2

Dies ist ein Problem mit der PHP-Datum-String-Parser. Siehe hier: http://derickrethans.nl/obtaining-the-next-month-in-php.html

@Mr. Lama hat ein Skript zu zeigen, was ein anderes Datum dieses Problem Auswirkungen: http://codepad.viper-7.com/E4gP0W

Die Lösung, die ich mit gegangen:

//Date:07/31/15 
$currentMonth = date('m'); 
//Result:07 
$lastMonth = date('m', strtotime('first day of -1 months')); 
//Result:06 
+0

Große Antwort auf ein verblüffendes Problem. – user2029890

1

-1 month wird als "gleicher Tag des Monats, letzter Monat" interpretiert. Wenn dieser Tag nicht existiert, läuft das Datum in den nächsten Monat über. Eigentlich ist das Ergebnis dasselbe wie strtotime("31.6.2015") - probier es aus!