Функция модификации DateTime пропускает февраль - PullRequest
1 голос
/ 30 апреля 2020

При добавлении месяца в метод DateTime::modify результат пропускается в феврале.

  • Почему не выводится 2020-02-31?
  • Как вывести 2020-02-29 используя DateTime? (Последний день месяца).
$date = new DateTime("2020-01-31");
echo $date->modify("+1 month")->format("Y-m-d"); // 2020-03-02

Ответы [ 2 ]

1 голос
/ 30 апреля 2020

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
0 голосов
/ 30 апреля 2020

Я предполагаю, что вы программируете на php. Если это так, в документации указано, что вы получите результаты, которые вы получаете php DateTime :: modify () .

В документации конкретно указано «Осторожно»

Пример # 2 Остерегайтесь при сложении или вычитании месяцев

 <?php
 $date = new DateTime('2000-12-31');

 $date->modify('+1 month');
 echo $date->format('Y-m-d') . "\n";

 $date->modify('+1 month');
 echo $date->format('Y-m-d') . "\n";
 ?>
 The above example will output:

 2001-01-31
 2001-03-03

Если вам просто нужно перейти к концу следующего +1 месяца, то, что мы часто делаем в R, это go до конца текущий месяц, а затем добавьте +1 день и затем go к концу месяца снова. Если вы знаете, что вы всегда в конце месяца, просто добавьте +1 день, а затем go к концу месяца.

В других публикациях есть дополнительные предложения в этом пространстве Как найти последний день месяца с даты?

Пример из этого поста:

 $date = new DateTime('now');
 $date->modify('last day of this month');
 echo $date->format('Y-m-d');
...