date()
Функции работы с датой и временем в PHP: date(), time(), strtotime() и объектно-ориентированный API DateTime с примерами
Введение
Практически в каждом приложении рано или поздно возникает необходимость отображать, сохранять или сравнивать дату: строка «опубликовано», обратный отсчёт, проверка срока действия. В этой главе объясняется, как работают инструменты PHP для работы с датой и временем, и когда следует использовать каждый из них. Мы начнём с повседневных функций — date(), time() и strtotime() — затем перейдём к манипуляциям и сравнению дат и завершим разбором наиболее часто встречающихся ошибок: работы с часовыми поясами и переходом на летнее время.
Работа с датами в PHP
PHP предлагает два взаимодополняющих набора инструментов для работы с датами:
- Процедурные функции —
date(),time(),mktime()иstrtotime()— которые работают с Unix-временной меткой (простое целое число: количество секунд, прошедших с 1 января 1970 года UTC). Они удобны для быстрого форматирования и арифметики. - Объектно-ориентированный API
DateTime— классыDateTime,DateIntervalиDateTimeZone— который более читаем для всего, что связано с интервалами, сравнениями или часовыми поясами, и является рекомендуемым подходом для нового кода.
В этой главе используются оба стиля, чтобы вы могли узнавать каждый из них в реальных кодовых базах.
Функция date()
Функция date() преобразует временну́ю метку в отформатированную строку. Первый параметр — строка формата, второй (необязательный) — временна́я метка; если временна́я метка опущена, date() использует текущее время.
Это выводит текущую дату в формате «Month Day, Year», например March 3, 2023.
Каждая буква в строке формата является заполнителем. В таблице ниже перечислены наиболее часто используемые символы:
| Символ | Значение | Пример |
|---|---|---|
Y | 4-значный год | 2023 |
y | 2-значный год | 23 |
m | Месяц, 2 цифры (01–12) | 03 |
n | Месяц без ведущего нуля | 3 |
F | Полное название месяца | March |
M | Сокращённое название месяца | Mar |
d | День месяца, 2 цифры | 03 |
j | День месяца без ведущего нуля | 3 |
l | Полное название дня недели | Friday |
H | Час, 24-часовой формат, 2 цифры | 14 |
h | Час, 12-часовой формат, 2 цифры | 02 |
i | Минуты, 2 цифры | 09 |
s | Секунды, 2 цифры | 05 |
A | AM / PM | PM |
Любой символ, не являющийся распознанным заполнителем, выводится буквально, поэтому date("Y-m-d H:i:s") даст значение вроде 2023-03-03 14:09:05. Чтобы вывести буквенный символ, который иначе был бы заполнителем, экранируйте его обратным слешем: date('l \t\h\e jS'). Полный список заполнителей см. в главе date-format().
Функция time()
Функция time() возвращает текущую Unix-временну́ю метку — количество секунд, прошедших с 1 января 1970 года UTC. Она не принимает аргументов и обычно служит отправной точкой для арифметики с датами, поскольку целые числа удобно складывать и сравнивать.
Это выводит текущую Unix-временну́ю метку — длинное целое число вроде 1646369616. Комбинируйте её с date() для форматирования «сейчас»: date("Y-m-d", time()). Подробнее см. главу time().
Функция strtotime()
Функция strtotime() разбирает дату, заданную текстом на английском языке — "March 3, 2023", "next Monday", "+2 weeks" — и возвращает соответствующую Unix-временну́ю метку. Она поразительно гибка, что делает её удобной для преобразования пользовательского ввода во временну́ю метку для форматирования или сравнения.
Это выводит Unix-временну́ю метку для 3 марта 2023 года: 1677801600.
Внимание: если
strtotime()не может разобрать строку, она возвращаетfalse, а не ошибку. Всегда проверяйте результат перед использованием —if (($ts = strtotime($input)) === false) { /* invalid date */ }— иначеfalseмолча приведётся к0, что отформатируется как 1 января 1970 года. Полную грамматику принимаемых выражений см. в главе strtotime().
Манипуляции с датами в PHP
Помимо форматирования дат, PHP предоставляет разнообразные функции для их изменения. Они позволяют прибавлять или вычитать время, сравнивать даты и многое другое.
Прибавление и вычитание времени с помощью strtotime()
strtotime() умеет не только разбирать фиксированные даты — она также понимает относительные выражения. Передайте базовую временну́ю метку вторым аргументом, а фразу вроде "+1 day", "-3 weeks" или "first day of next month" — первым, и вы получите новую временну́ю метку.
Это выведет дату, следующую за 3 марта 2023 года, то есть «March 4, 2023».
Методы DateTime::add() и DateTime::sub()
Объектно-ориентированные методы DateTime::add() и DateTime::sub() добавляют или вычитают DateInterval из объекта DateTime. DateInterval строится из строки длительности в формате ISO 8601: P1D означает «период в 1 день», P2W — две недели, PT1H30M — один час и тридцать минут (символ T отделяет дату от времени).
Этот стиль предпочтителен для нового кода, поскольку операция читается как предложение, а объект сам отслеживает свой часовой пояс.
Это выводит дату, следующую за 3 марта 2023 года: March 4, 2023. Подробнее рассматривают эту тему отдельные главы date-add() и date-sub(), а date-diff() показывает, как получить интервал между двумя объектами DateTime.
Сравнение дат в PHP
Поскольку временны́е метки — это обычные целые числа, вы можете сравнить две даты с помощью стандартных операторов <, > и ==, предварительно преобразовав каждую в временну́ю метку с помощью strtotime().
Это выведет Date 1 is earlier than Date 2. При сравнении объектов DateTime можно использовать те же операторы напрямую ($a < $b) без преобразования в временны́е метки.
Часовые пояса и переход на летнее время
Самая сложная часть работы с датами — убедиться, что они относятся к одному и тому же моменту в разных регионах. date() и time() интерпретируют временны́е метки в настроенном по умолчанию часовом поясе PHP, поэтому важно правильно задать этот параметр.
Функция date_default_timezone_set()
date_default_timezone_set() устанавливает часовой пояс по умолчанию для всех функций работы с датой и временем на протяжении всего запроса. Вызывайте её один раз в начале скрипта, передавая корректный идентификатор IANA, например America/New_York или Europe/London.
<?php
date_default_timezone_set("America/New_York");
echo date("Y-m-d H:i:s");
?>Список допустимых идентификаторов приведён в главе php-timezones; чтение текущей настройки рассматривается в date-default-timezone-get().
Класс DateTimeZone
Если в одном скрипте нужны разные часовые пояса — например, для отображения времени события пользователям из нескольких регионов — однократной установки по умолчанию недостаточно. Класс DateTimeZone позволяет конкретному объекту DateTime иметь собственный часовой пояс:
<?php
$timezone = new DateTimeZone("America/New_York");
$date = new DateTime("2023-03-03 09:00", $timezone);
echo $date->format("Y-m-d H:i T");
?>Это форматирует дату по нью-йоркскому времени и выводит аббревиатуру пояса (T), например 2023-03-03 09:00 EST.
Работа с переходом на летнее время
Переход на летнее время (DST) переводит часы вперёд или назад, поэтому смещение для зоны вроде America/New_York непостоянно (EST или EDT). PHP автоматически обрабатывает переход, если вы используете именованный пояс, а не жёстко заданное смещение. Символ формата date() — I (прописная буква «i») — сообщает, действует ли сейчас летнее время: 1 если да, 0 если нет.
Это выводит, действует ли переход на летнее время для текущего часового пояса по умолчанию.
Заключение
Теперь у вас есть основной набор инструментов для работы с датами в PHP: date() для форматирования, time() и strtotime() для получения и разбора временны́х меток, семейство DateTime для прибавления, вычитания и сравнения, а также DateTimeZone для корректной работы с разными регионами. Практическое правило: используйте процедурные функции для быстрого разового форматирования, а объектно-ориентированный API DateTime — для всего, что связано с интервалами, сравнениями или несколькими часовыми поясами. Для более широкого обзора см. PHP Date and Time.