W3docs

date_modify()

Полное руководство по функции PHP date_modify: синтаксис, примеры, подводные камни при работе с месяцами и использование DateTimeImmutable.

В этом руководстве рассматривается метод PHP DateTime::modify() — объектно-ориентированный аналог процедурной функции date_modify(). Объясняется, как modify() разбирает строки относительных дат, что он возвращает, в чём заключается проблема переполнения месяца, с которой сталкивается большинство разработчиков, и как избежать случайного изменения даты.

Что такое DateTime::modify()?

modify() — встроенный метод класса DateTime, который изменяет хранимую дату/время с помощью строки в относительном формате, например +10 days, -3 months или next monday. Используйте его всякий раз, когда вам нужна арифметика дат — сдвиг дедлайна вперёд, перемотка временной метки назад или переход к следующему рабочему дню — без ручного вычисления секунд.

Два свойства выделяют modify() среди остальных методов; запомните их прежде, чем переходить к примерам:

  • Он изменяет объект на месте — меняет тот же DateTime, на котором вызван, а не возвращает новую копию.
  • Он принимает ту же грамматику относительных форматов, которую PHP использует при создании дат из строк, поэтому всё, что понимает new DateTime('+1 week'), понимает и modify().

Синтаксис

public DateTime::modify(string $modifier): DateTime|false
  • $modifier — строка в относительном формате (например, +1 day, -2 weeks, first day of next month, 14:00).
  • Возвращает тот же object DateTime в случае успеха (что позволяет строить цепочки вызовов) или false при ошибке (например, если строка не может быть разобрана).

Поскольку метод возвращает сам объект, следующие две строки эквивалентны — исходный $date изменяется в любом случае:

$date->modify('+1 day');          // mutates $date, return value ignored
$date = $date->modify('+1 day');  // mutates $date AND reassigns the same object

Совет: Если $modifier поступает из пользовательского ввода, всегда проверяйте результат на false перед использованием — неверно сформированная строка вернёт false, а не выбросит исключение.

Примеры

Пример 1: Прибавление дней к дате

Прибавление 10 дней к фиксированной дате с базовой обработкой ошибок:

Прибавление дней к дате в PHP

php— editable, runs on the server

Вывод:

2023-03-11

Пример 2: Вычитание месяцев из даты

Вычитание 3 месяцев из фиксированной даты:

Вычитание месяцев из даты в PHP

php— editable, runs on the server

Вывод:

2022-12-01

Пример 3: Установка времени в конкретное значение

Установка времени на 14:00 для фиксированной даты:

Установка времени в конкретное значение в PHP

php— editable, runs on the server

Вывод:

2023-03-01 14:00:00

Обратите внимание: modify('14:00') устанавливает время на 14:00, не затрагивая дату — относительные форматы, указывающие только время, воздействуют только на временну́ю часть, но не на день.

Пример 4: Объединение нескольких единиц в одном вызове

Можно совмещать несколько относительных единиц в одной строке модификатора, разделяя их пробелами. Они применяются слева направо:

<?php

$date = new DateTime('2023-03-01');
$date->modify('+1 week +2 days');
echo $date->format('Y-m-d');

Вывод:

2023-03-10

Проблема переполнения месяца

Прибавление или вычитание месяцев не ограничивается концом более короткого месяца — происходит переполнение в следующий месяц. Посмотрите, что происходит при прибавлении одного месяца к 31 января:

<?php

$date = new DateTime('2023-01-31');
$date->modify('+1 month');
echo $date->format('Y-m-d');

Вывод:

2023-03-03

Поскольку в феврале 2023 года только 28 дней, «31 января + 1 месяц» приходится на несуществующее «31 февраля», которое PHP переводит на 3 марта. Если вам нужен последний день следующего месяца, используйте абсолютный относительный формат:

<?php

$date = new DateTime('2023-01-31');
$date->modify('last day of next month');
echo $date->format('Y-m-d');

Вывод:

2023-02-28

Избегайте случайной мутации с DateTimeImmutable

Поскольку modify() изменяет объект на месте, совместное использование одного DateTime в разных частях кода может привести к трудноуловимым ошибкам — изменение в одном месте затрагивает все ссылки на него. Если вы хотите, чтобы каждая операция возвращала новое значение, оставляя оригинал нетронутым, используйте DateTimeImmutable, чей метод modify() возвращает новый объект:

<?php

$original = new DateTimeImmutable('2023-03-01');
$nextWeek = $original->modify('+7 days');

echo $original->format('Y-m-d') . "\n"; // unchanged
echo $nextWeek->format('Y-m-d');

Вывод:

2023-03-01
2023-03-08

Полезные относительные форматы

modify() принимает разнообразную грамматику относительных выражений. Несколько распространённых примеров:

МодификаторЗначение
+5 days, -2 weeksПрибавить или вычесть заданное количество единиц
+1 year +6 monthsОбъединить несколько единиц в одной строке
next monday, last fridayПерейти к указанному дню недели
first day of this monthПерейти на 1-е число текущего месяца
last day of next monthПерейти на последний день следующего месяца
tomorrow, yesterdayСдвинуть на один день (и сбросить время на полночь)
14:30, midnightУстановить только временну́ю часть

Связанные функции

  • date_add() — прибавить DateInterval к дате.
  • date_sub() — вычесть DateInterval из даты.
  • date_diff() — получить разницу между двумя датами.
  • date_format() — форматировать объект DateTime в строку.

Итоги

DateTime::modify() применяет строку в относительном формате к дате, изменяя объект на месте и возвращая его (или false при ошибке). Метод идеально подходит для арифметики дат и перехода к именованным дням, однако помните о двух вещах: арифметика месяцев переполняется за пределы коротких месяцев, а мутация является общей — используйте DateTimeImmutable, если вам нужно сохранить исходное значение.

Практика

Практика
Что позволяет делать функция date_modify() в PHP?
Что позволяет делать функция date_modify() в PHP?
Was this page helpful?