date_timezone_set()
Узнайте, как date_timezone_set() в PHP переводит объект DateTime в другой часовой пояс без изменения момента времени. Синтаксис, DST и примеры.
Введение
date_timezone_set() изменяет часовой пояс существующего object DateTime. Важно понимать: функция не меняет абсолютный момент времени — она меняет представление на часах для того же момента. Один и тот же момент просто выражается в другом часовом поясе: отображаемые часы и минуты сдвигаются, а сама точка на временной шкале остаётся неизменной.
Это правильный инструмент, когда у вас есть дата/время в одном поясе и нужно отобразить их в другом: например, для перевода сохранённой UTC-метки в локальное время пользователя или сравнения событий, записанных в разных регионах.
date_timezone_set() — процедурный псевдоним метода DateTime::setTimezone(): оба делают ровно одно и то же.
Синтаксис
date_timezone_set(DateTime $object, DateTimeZone $timezone): DateTime|false$object— objectDateTime, часовой пояс которого нужно изменить.$timezone— objectDateTimeZone, задающий целевой пояс (например,new DateTimeZone('Asia/Tokyo')).
Функция изменяет $object на месте и возвращает тот же экземпляр при успехе (удобно для цепочек вызовов) либо false при ошибке. Поскольку она модифицирует исходный object, отдельной «копии» не создаётся — изменяется именно переданный object.
Базовый пример
2023-03-03 21:00:00Object создаётся с временем 12:00 по Лондону (Europe/London, то есть UTC+0 в марте). Токио опережает Лондон на 9 часов, поэтому тот же момент отображается как 21:00. Сам момент не изменился — изменился лишь часовой пояс отображения.
Момент остаётся прежним — меняется только отображение
Это самое важное, что нужно понять о date_timezone_set(). Сравните значение до и после преобразования:
<?php
$date = new DateTime('2023-03-03 12:00:00', new DateTimeZone('Europe/London'));
echo $date->format('Y-m-d H:i:s P'), "\n"; // before
date_timezone_set($date, new DateTimeZone('Asia/Tokyo'));
echo $date->format('Y-m-d H:i:s P'), "\n"; // after2023-03-03 12:00:00 +00:00
2023-03-03 21:00:00 +09:00Показания часов и UTC-смещение изменились, однако 12:00 +00:00 и 21:00 +09:00 — это один и тот же момент времени. Если вам нужен только абсолютный момент (например, UNIX-timestamp), он останется неизменным.
Если вы хотите заменить показания часов без конвертации, не используйте эту функцию — задайте время напрямую с помощью
date_time_set().
Переход на летнее время обрабатывается автоматически
Поскольку преобразование выполняется через настоящий DateTimeZone, правила перехода на летнее время (DST) применяются автоматически. Нью-Йорк находится в UTC-5 зимой и в UTC-4 летом, и date_timezone_set() автоматически выбирает правильное смещение для указанной даты:
<?php
$utc = new DateTime('2023-06-21 12:00:00', new DateTimeZone('UTC'));
date_timezone_set($utc, new DateTimeZone('America/New_York'));
echo $utc->format('Y-m-d H:i:s');2023-06-21 08:00:00В июне Нью-Йорк работает по восточному летнему времени (UTC-4), поэтому 12:00 UTC превращается в 08:00. Запустите тот же код с датой в январе — и получите 07:00 (UTC-5) без каких-либо изменений в коде. Вот почему всегда следует использовать идентификаторы часовых поясов IANA, такие как America/New_York, а не фиксированные смещения вроде -05:00.
Процедурный и объектно-ориентированный стиль
date_timezone_set($obj, $tz) и $obj->setTimezone($tz) взаимозаменяемы. Форма метода обычно читается лучше и удобна для цепочек вызовов:
<?php
$london = (new DateTime('2023-03-03 12:00:00', new DateTimeZone('Europe/London')))
->setTimezone(new DateTimeZone('Asia/Tokyo'));
echo $london->format('Y-m-d H:i:s');2023-03-03 21:00:00Типичные сценарии использования
- Отображение UTC-времени в часовом поясе пользователя. Храните все метки времени в UTC, а при выводе конвертируйте их с помощью
date_timezone_set()в предпочтительный пояс каждого пользователя. - Нормализация времени из разных регионов перед сравнением или сортировкой.
- Формирование региональных отчётов, в которых одно и то же событие отображается одновременно в нескольких часовых поясах.
На что обратить внимание
- Функция изменяет исходный object. Если нужно сохранить исходное значение, сначала клонируйте его:
$copy = clone $date;, а затем конвертируйте$copy. - Функция не разбирает и не устанавливает новую дату — она лишь перепроецирует существующий момент. Используйте
date_create()для созданияDateTimeиdate_time_set()для замены времени. - Чтобы узнать часовой пояс, который в данный момент связан с object, используйте
date_timezone_get(). - Не путайте эту функцию с
date_default_timezone_set(), которая устанавливает часовой пояс по умолчанию для всех функций даты и времени в скрипте — это совершенно другая задача.
Диаграмма
graph LR
A[DateTime Object] --> B((date_timezone_set))
C[Target DateTimeZone] --> B
B --> D[Same instant, new wall-clock display]