У меня есть сценарий, который получает текущий и последний месяц в 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;
Это проблема с парсером 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'));