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.
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? –
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 . –
Sempre stupito quando trovo qualcuno che ancora non usa https://github.com/briannesbitt/Carbon per fare le date in PHP. – ceejayoz