Почему дата PHP ('m', strtotime ('- 1 months')) не работает корректно на сегодняшний день? 07/31

У меня есть сценарий, который получает текущий и последний месяц в PHP так:

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

Сегодня бывает 31 или конец июля. Можно ли ожидать этого результата от PHP?

При использовании -31 дня результат будет таким, как ожидалось:

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

Вот более чистый тестовый пример , который не истекает:

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

Я уверен, что это проблема с документацией, потому что в руководстве четко сказано это (основное внимание):

Относительные значения месяца рассчитываются исходя из длины месяцев , через которые они проходят. Примером может служить «+2 месяц 2011-11-30», который будет производить «2012-01-30». Это связано с тем, что ноябрь составляет 30 дней, а декабрь составляет 31 день в длину, что составляет 61 день.

… и это неправильно.

У PHP-трекера есть много обманов . Они все закрыты, как не ошибка . Вот соответствующий комментарий 2009 года, который объясняет это:

Я согласен, что это раздражающее поведение.

Кроме того, реализация проблематична. В основном, если вы используете «+1 месяц», он принимает номер месяца, добавляет 1 и анализирует результат как новую дату .

Если вы используете «+1 месяц» в первый месяц месяца, он устанавливает дату в следующую первую часть месяца.

Такое поведение создает впечатление, что php учитывает длину месяца, что неверно.

Но если вы используете «+1 месяц» в последний день месяца, результат является неожиданным, так как 2009-05-31 становится 2009-06-31, который является недопустимой датой, а затем интерпретируется как 2009-07-01.

Это следует, по крайней мере, упомянуть в документации .

Вы можете сделать это

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

ДЕМО: http://codepad.viper-7.com/kokWi8

Это проблема с парсером date-string PHP. См. Здесь: http://derickrethans.nl/obtaining-the-next-month-in-php.html

@Мистер. Ллама сделал сценарий, показывающий, какие другие даты эта проблема влияет: http://codepad.viper-7.com/E4gP0W

Решение, с которым я пошел:

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

-1 month интерпретируется как «тот же день месяца, в прошлом месяце». Если этот день не существует, дата перейдет в следующий месяц. На самом деле результат такой же, как strtotime("31.6.2015") – попробуйте!

В месяц есть «с» . Это должно быть так:

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