PHP функция date_date_set()
Узнайте, как date_date_set() и DateTime::setDate() изменяют год, месяц и день объекта DateTime в PHP, с примерами и типичными ошибками.
В PHP функции date_date_set() и её объектно-ориентированный аналог DateTime::setDate() устанавливают новую дату (год, месяц и день) на существующем объекте DateTime. Временна́я часть объекта остаётся нетронутой — изменяется только календарная дата. Это аналог метода DateTime::setTime(), который меняет только время.
Используйте его, когда у вас уже есть объект DateTime и вы хотите переместить его на конкретный день, не создавая объект заново из строки.
Синтаксис
setDate() доступен как в виде метода, так и в виде процедурной функции. Обе формы делают одно и то же:
Синтаксис DateTime::setDate() и date_date_set()
// Object-oriented style
$datetime->setDate($year, $month, $day);
// Procedural style
date_date_set($datetime, $year, $month, $day);Где:
$datetime— объектDateTime, который нужно изменить.$year— новый год (например,2024).$month— новый месяц (1–12).$day— новый день месяца (1–31).
Метод возвращает тот же объект DateTime, поэтому вызовы можно объединять в цепочку. Существующее время, микросекунды и часовой пояс объекта при этом сохраняются.
Пример использования
Установим новую дату на объекте DateTime, сохранив исходное время:
Пример метода PHP DateTime::setDate()
Мы создаём DateTime для 2000-01-01 12:30:00, затем вызываем setDate(), чтобы изменить дату на 15 июля 2024 года. Поскольку setDate() затрагивает только календарную дату, время 12:30:00 остаётся прежним. Затем мы используем метод format() для вывода результата:
2024-07-15 12:30:00Процедурный стиль
Если вы предпочитаете (или работаете со старым кодом), то же самое изменение можно записать с помощью date_date_set(). Эта функция принимает объект в качестве первого аргумента:
<?php
$date = date_create('2000-01-01');
date_date_set($date, 2024, 7, 15);
echo $date->format('Y-m-d');Это выведет 2024-07-15. Здесь date_create() создаёт объект — это процедурный эквивалент new DateTime.
Выход за пределы диапазона дней: перенос на следующий месяц
Как и остальная часть API DateTime, метод setDate() не проверяет корректность дня относительно длины месяца. Вместо этого он нормализует значение, перенося излишек в следующий месяц. Запрос «31 февраля» даст вам дату в марте:
<?php
$date = new DateTime('2024-01-31');
$date->setDate(2024, 2, 31);
echo $date->format('Y-m-d');Это выведет 2024-03-02: в феврале 2024 года 29 дней, поэтому 31-е число — это 2 дня после конца месяца, что соответствует 2 марта. Такой перенос удобен для арифметики с датами, но является распространённым источником скрытых ошибок, если вы ожидали исключения. Чтобы сдвинуть дату на относительное значение, используйте modify(), add() или sub().
Изменяемый и неизменяемый объекты
DateTime является изменяемым: setDate() модифицирует объект на месте и возвращает тот же объект. Если значение используется совместно в нескольких местах кода, все ссылки увидят изменение. Чтобы избежать случайных мутаций, используйте DateTimeImmutable, чей setDate() возвращает новый экземпляр, оставляя исходный объект нетронутым:
<?php
$original = new DateTimeImmutable('2000-01-01');
$changed = $original->setDate(2024, 7, 15);
echo $original->format('Y-m-d'), ' | ', $changed->format('Y-m-d');Это выведет 2000-01-01 | 2024-07-15: $original остаётся неизменным, а $changed содержит новую дату. При использовании изменяемого DateTime обе переменные указывали бы на один и тот же изменённый объект.
Связанные методы
setDate() редко используется в одиночку. Часто его комбинируют с:
setTime()— изменить часы/минуты/секунды того же объекта.setTimezone()— конвертировать объект в другой часовой пояс.date_default_timezone_set()— задать часовой пояс по умолчанию для всего скрипта.new DateTime/date_create()— создать объект в первую очередь.
Заключение
DateTime::setDate() (и эквивалентная date_date_set()) — это чистый объектно-ориентированный способ изменить год, месяц и день объекта DateTime с сохранением времени и часового пояса. Запомните два важных момента: дни, выходящие за пределы диапазона, переносятся на следующий месяц, а не вызывают исключение; изменяемый DateTime меняется на месте — используйте DateTimeImmutable, если вам нужно, чтобы исходный объект оставался нетронутым.