2015-07-31 14 views
6

Ho uno script che ottiene il mese corrente e l'ultimo in PHP in questo modo:Perché la data di PHP ('m', strtotime ('- 1 months')) non funziona correttamente per oggi? 07/31

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

Oggi sembra essere il 31 o alla fine del mese di luglio. Questo risultato è previsto da PHP?

Quando si utilizza -31 giorni il risultato è come previsto:

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

mese-matematica è sempre rischioso. cos'è un mese? "oggi in ($ curmonth-1)" ?, cosa succede se è il 31 marzo, vuoi il 31 febbraio o il 28 febbraio? feb 29? –

+1

Sembra che non siano gli unici giorni di pausa di -1 mesi su: http://codepad.viper-7.com/E4gP0W Il 31 di un mese non mi sorprende, ma il 29 e il 30 marzo fanno . –

+1

Sempre stupito quando trovo qualcuno che ancora non usa https://github.com/briannesbitt/Carbon per fare le date in PHP. – ceejayoz

risposta

2

Ecco un cleaner test case che non ha scadenza:

<?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" 

Sono abbastanza sicuro che si tratta di un problema di documentazione, perché il manuale afferma chiaramente questo (sottolineatura mia):

valori relativi al mese sono calcolati in base alla lunghezza di mesi che passano attraverso. Un esempio potrebbe essere "+2 mese 2011-11-30", che produrrebbe "2012-01-30". Ciò è dovuto al fatto che novembre è di 30 giorni di lunghezza e dicembre di 31 giorni di lunghezza, producendo un totale di 61 giorni pari a .

... ed è sbagliato.

PHP bug tracker ha tons of dupes su questo. Sono tutti chiusi come non un bug. Ecco un rilevante comment from 2009 che lo spiega:

sono d'accordo che questo è un comportamento fastidioso.

Inoltre, l'implementazione è problematica. Fondamentalmente se si utilizza "+1 month" prende il numero del mese, aggiunge 1 e analizza il risultato come una nuova data.

Se si utilizza "+1 mese" il primo del mese, imposta la data su il primo giorno del mese successivo.

Questo comportamento dà l'impressione, che php considera la lunghezza di un mese, che non è vero.

Ma se si utilizza '1 mese' l'ultimo giorno di un mese, il risultato è inaspettato come 2009-05-31 diventa 2009/06/31, che è una data non valida e poi interpretata come 2009-07-01.

Questo deve essere menzionato nella documentazione.

-1

c'è "s" in eccesso nel mese. Dovrebbe essere così:

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

non fa differenza. PHP non è una grammatica nazista e "1 mese" e "1 mese" sono identici per quanto riguarda la questione. –

+1

Ah si va bene ... Devo cancellare la risposta? – lisztomania

+1

In effetti, l'extra 's' è permesso/facoltativo. La [documentazione] (http://php.net/manual/en/datetime.formats.relative.php) lo conferma. – axiac

2

Si può fare in questo modo

$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: http://codepad.viper-7.com/kokWi8

2

questo è un problema con il parser data-stringa di PHP. Vedi qui: http://derickrethans.nl/obtaining-the-next-month-in-php.html

@Mr. Llama ha fatto uno script che mostra quello che altre date questo numero di effetti: http://codepad.viper-7.com/E4gP0W

La soluzione sono andato con:

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

Ottima risposta a un problema di perplessità. – user2029890

1

-1 month viene interpretato come "lo stesso giorno del mese, il mese scorso". Se questo giorno non esiste, la data si riversa nel mese successivo. In realtà il risultato è lo stesso di strtotime("31.6.2015") - provalo!