PHP DateTime::modify("+n month")
добавляет от 28 до 31 дня к текущему дню, в зависимости от месяца и года.
Решение
Я предлагаю вам увеличить месяцы с первого дня месяц с использованием методов modify
и format
:
// Instanciates the DateTime object.
$date = new DateTime("2020-01-01");
// Adds a month to the date.
$date->modify("+1 month"); // 2020-02-01
// Format the date with "t" (gets the last day of the month).
$date->format("Y-m-t"); // 2020-02-29
Увеличение с первого дня месяца никогда не поднимет февральскую проблему , которая довольно часто, думая, что PHP DateTime умно добавит месяц с 2020-02-29
и выведет 2020-03-31
.
Почему это происходит?
В григорианском календаре , средняя продолжительность месяца составляет 30,436875 дней:
- 30 дней в апреле, июне, сентябре и ноябре;
- 31 день в январе , Март, май, июль, август, октябрь и декабрь;
- 28 дней или 29 дней (в високосных годах ) в феврале.
PHP добавит к текущей дате точное количество дней в данном месяце.
Таким образом, PHP отрегулирует дата после первого врезания, если вы увеличиваете с последнего дня месяца.
Например:
Давайте добавим месяц с последнего дня марта (31-го).
Поскольку текущий месяц (март) содержит 31 день, PHP будет увеличиваться на 31 день до даты. Добавление 31 дня с 2020-03-31
приведет к пропуску всего месяца апреля.
$date = new DateTime("2020-03-31"); // 2020-03-31
echo $date->modify("+1 month")->format("Y-m-d"); // 2020-05-01 | Added 31 days (since March has 31 days).
echo $date->modify("+1 month")->format("Y-m-d"); // 2020-06-01 | Added 31 days (since the new date is May 1st, which is a month with 31 days).
echo $date->modify("+1 month")->format("Y-m-d"); // 2020-07-01 | Added 30 days
Теперь давайте добавим месяц к последнему дню (30-го) апреля.
Мы можем обратите внимание, что, поскольку в течение следующих месяцев все имеют более 30 дней, последний день остается неизменным, до февраля следующего года . Поскольку в феврале всегда есть от 28 до 29 дней, добавление к нему 31 дня будет проходить месяц, а итоговая дата будет 2 марта.
$date = new DateTime("2020-04-30");
echo $date->modify("+1 month")->format("Y-m-d"); // 2020-05-30 | Added 30 days.
echo $date->modify("+1 month")->format("Y-m-d"); // 2020-06-30 | Added 31 days.
echo $date->modify("+1 month")->format("Y-m-d"); // 2020-07-30 | Added 30 days.
// ...
echo $date->modify("+1 month")->format("Y-m-d"); // 2021-01-30 | Added 31 days
echo $date->modify("+1 month")->format("Y-m-d"); // 2021-03-02 | Added 31 days (since January has 31 days).
echo $date->modify("+1 month")->format("Y-m-d"); // 2021-04-02 | Added 31 days (since the new date is March 2nd, which is a month with 31 days).
Именно поэтому рекомендуется увеличивать месяцы с первого дня месяца, поскольку 1-е является общим для всех месяцев.
$date = new DateTime("2020-01-01"); // 2020-01-01
echo $date->modify("+1 month")->format("Y-m-d"); // 2020-02-01 | Added 31 days
echo $date->modify("+1 month")->format("Y-m-d"); // 2020-03-01 | Added 29 days (since 2020 is leap year, yee haw).
echo $date->modify("+1 month")->format("Y-m-d"); // 2020-04-01 | Added 31 days