2015-07-31 8 views
6

Mam skrypt, który pobiera bieżący i ostatni miesiąc w PHP tak:Dlaczego daty PHP ("m", strtotime ("- 1 miesiące")) nie działają poprawnie na dziś? 31/07

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

Dziś dzieje się 31 lub z końcem miesiąca lipca. Czy tego wyniku można się spodziewać po PHP?

Podczas korzystania -31 dni wynik jest zgodnie z oczekiwaniami:

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

Miesiąc matematyki jest zawsze ryzykowny. co to jest miesiąc? "dzisiaj w ($ curmonth-1)"?, co się stanie, jeśli będzie 31 marca, czy chcesz 31 lutego, czy 28 lutego? feb 29? –

+1

Wygląda na to, że nie są to jedyne dni '-1 miesiąca' przerwy na: http://codepad.viper-7.com/E4gP0W 31 dnia miesiąca nie zaskakuje mnie, ale 29 i 30 marca . –

+1

Zawsze zaskoczony, gdy ktoś nadal nie używa https://github.com/briannesbitt/Carbon do robienia dat w PHP. – ceejayoz

Odpowiedz

2

Oto cleaner test case że nie wygasa:

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

Jestem prawie pewien, że jest to problem z dokumentacją, ponieważ instrukcja wyraźnie stwierdza to (nacisk mój):

Względne wartości miesiąc oblicza na podstawie długości miesięcy że przechodzą one przez. Przykładem może być "+2 miesiąc 2011-11-30", , który wyświetli "2012-01-30". Wynika to z faktu, że listopad ma być 30 dni długości, a grudzień ma 31 dni długości, co daje łącznie 612 dni w roku .

... i jest źle.

Monitorowanie błędów PHP ma na ten temat tons of dupes. Wszystkie są zamknięte jako a nie jako błąd. Oto odpowiednia comment from 2009, która wyjaśnia:

Zgadzam się, że jest to denerwujące zachowanie.

Również wdrożenie jest problematyczne. Zasadniczo , jeśli używasz '+1 miesiąca', to ma numer miesiąca, dodaje 1 i analizuje wynik jako nowy date.

Jeśli użyjesz "+1 miesiąca" pierwszego dnia miesiąca, ustawi on datę na następnego dnia miesiąca.

To zachowanie sprawia wrażenie, że php bierze pod uwagę długość miesięcznie, co nie jest prawdą.

Ale jeśli używasz „” +1 miesiąc w ostatnim dniu miesiąca, wynik jest nieoczekiwany jak 2009-05-31 staje 2009-06-31 która jest nieważna data a następnie interpretowane jako 2009-07-01.

Ten numer powinien być przynajmniej wymieniony w dokumentacji.

-1

Jest "s" w nadmiarze w miesiącu. Powinno być tak:

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

nie robi różnicy. PHP nie jest gramatyką nazistowską, a "1 miesiąc" i "1 miesiąc" są identyczne, o ile to dotyczy. –

+1

Ah tak w porządku ... Czy powinienem usunąć odpowiedź? – lisztomania

+1

Rzeczywiście, dodatkowe 's' jest dozwolone/opcjonalne. Potwierdza to [dokumentacja] (http://php.net/manual/en/datetime.formats.relative.php). – axiac

2

Można to zrobić w ten sposób

$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

1

-1 month jest interpretowany jako "ten sam dzień miesiąca, ostatni miesiąc". Jeśli ten dzień nie istnieje, data przepełni się do następnego miesiąca. W rzeczywistości wynik jest taki sam jak strtotime("31.6.2015") - spróbuj!

Powiązane problemy