PHP Date
Функции даты в PHP необходимы для работы с датами и временем. В этом руководстве мы рассмотрим основные инструменты и классы.
Введение
Почти каждое приложение должно читать, форматировать даты или выполнять с ними арифметические операции: записи в журналах, метки «опубликовано 3 дня назад», планирование, проверка сроков действия. PHP предоставляет два параллельных инструментария:
- Процедурные функции, построенные на основе Unix-метки времени — целого числа, отсчитывающего секунды с 1 января 1970 года, 00:00:00 UTC. Сюда относятся
time(),date(),strtotime()иmktime(). - Объектно-ориентированный API
DateTime—DateTime,DateTimeImmutable,DateTimeZoneиDateInterval— который безопаснее для арифметики и работы с часовыми поясами.
На этой странице рассматриваются наиболее часто используемые функции и классы, когда следует выбирать каждый из них, а также типичная ошибка с часовыми поясами, на которую натыкаются почти все.
Заметка о часовых поясах
По умолчанию PHP использует часовой пояс, настроенный в php.ini (параметр date.timezone). Если он не задан, результаты могут различаться на разных серверах. Устанавливайте его явно в начале скрипта или передавайте DateTimeZone каждому объекту:
date_default_timezone_set('UTC');См. Часовые пояса PHP для полного списка допустимых идентификаторов и информации о преобразовании между поясами.
Функция date()
date(string $format, ?int $timestamp = null) форматирует метку времени в строку, удобную для чтения. Если метку времени не указать, используется текущее время. Это основной инструмент для отображения дат.
echo date('Y-m-d H:i:s'); // e.g. 2023-10-25 14:30:00
echo date('l, F j, Y'); // e.g. Wednesday, October 25, 2023Строка format состоит из символов-заполнителей. Наиболее употребительные из них:
| Символ | Значение | Пример |
|---|---|---|
Y | 4-значный год | 2023 |
m | Месяц с ведущим нулём | 10 |
d | День месяца с ведущим нулём | 25 |
H | Час в 24-часовом формате с ведущим нулём | 14 |
i | Минуты с ведущим нулём | 30 |
s | Секунды с ведущим нулём | 00 |
l | Полное название дня недели | Wednesday |
F | Полное название месяца | October |
Чтобы вывести букву, которая также является символом формата, экранируйте её обратным слешем: date('\T\o\d\a\y: Y-m-d').
Функция time()
time() возвращает текущую Unix-метку времени в виде целого числа. Используйте её всякий раз, когда нужно числовое «сейчас» для хранения, сравнения или арифметики.
$now = time();
echo $now; // an integer such as 1698241800
// One hour from now:
echo date('Y-m-d H:i:s', $now + 3600);Поскольку метка времени — это просто целое число секунд, к ней можно напрямую прибавлять или вычитать промежутки времени (+ 3600 для часа, + 86400 для дня). Для чего-либо сложнее нескольких фиксированных смещений предпочтительнее использовать арифметику DateTime, описанную ниже.
Функция strtotime()
strtotime(string $datetime, ?int $baseTimestamp = null) разбирает текстовую запись даты/времени на английском языке в метку времени, возвращая false при ошибке. Функция понимает как абсолютные строки, так и относительные фразы.
echo strtotime('2023-10-25 14:30:00'); // 1698244200 (UTC)
echo "\n";
var_dump(strtotime('next monday')); // a future timestamp, or false if unparseable$tomorrow = strtotime('+1 day');
echo date('Y-m-d', $tomorrow);Всегда проверяйте на false перед использованием результата, поскольку опечатка приводит к тихому сбою, а не к исключению.
Функция mktime()
mktime(int $hour, int $minute, int $second, int $month, int $day, int $year) создаёт метку времени из отдельных компонентов. Обратите внимание, что аргументы передаются сначала для времени, затем для даты.
$timestamp = mktime(0, 0, 0, 12, 31, 2023);
echo date('Y-m-d', $timestamp); // 2023-12-31mktime() нормализует значения за пределами допустимого диапазона, что удобно: mktime(0, 0, 0, 13, 1, 2023) преобразует «13-й месяц» в январь 2024 года.
Класс DateTime
new DateTime(string $datetime = 'now', ?DateTimeZone $timezone = null) оборачивает дату в объект, который можно форматировать, сравнивать и изменять с помощью вызовов методов. (Функция date_create() является процедурным псевдонимом того же конструктора.)
$date = new DateTime('2023-10-25', new DateTimeZone('UTC'));
echo $date->format('Y-m-d'); // 2023-10-25DateTime является изменяемым — методы вроде modify() изменяют объект на месте. Это источник незаметных ошибок при совместном использовании объекта, поэтому обычно предпочтительнее иммутабельная версия, описанная ниже.
Класс DateTimeImmutable
DateTimeImmutable имеет тот же API, что и DateTime, но каждый изменяющий метод возвращает новый объект, оставляя оригинал нетронутым. Для современного кода это более безопасный вариант по умолчанию.
$date = new DateTimeImmutable('2023-10-25');
$newDate = $date->modify('+1 day');
echo $date->format('Y-m-d'); // 2023-10-25 (unchanged)
echo "\n";
echo $newDate->format('Y-m-d'); // 2023-10-26Метод DateTime::format()
format(string $format) преобразует объект DateTime или DateTimeImmutable в строку. Он принимает те же символы формата, что и функция date().
$date = new DateTimeImmutable('2023-10-25 14:30:00');
echo $date->format('l, F j, Y'); // Wednesday, October 25, 2023Арифметика дат и разница между датами
Объектный API отлично подходит для арифметики. Используйте DateInterval (строки длительности ISO-8601) для прибавления или вычитания, и diff() для сравнения двух дат:
$start = new DateTimeImmutable('2023-10-25');
$later = $start->add(new DateInterval('P10D')); // P10D = 10 days
echo $later->format('Y-m-d'); // 2023-11-04
$diff = $start->diff(new DateTimeImmutable('2023-12-31'));
echo "\n" . $diff->days . ' days apart'; // 67 days apartВыбор подходящего инструмента
- Нужно быстро отформатировать «сейчас»? Используйте
date(). - Храните или сравниваете момент в числовом виде? Используйте
time()/ Unix-метки времени. - Разбираете пользовательский или журнальный ввод? Используйте
strtotime()(и проверяйте наfalse). - Выполняете арифметику, вычисляете разницы или конвертируете часовые пояса? Используйте
DateTimeImmutableсDateInterval.
Типичные ошибки
- Незаданный часовой пояс. Без
date_default_timezone_set()или значения вphp.iniрезультаты зависят от сервера. Устанавливайте его один раз в самом начале. strtotime()возвращаетfalseдля нераспознанных строк — функция никогда не генерирует исключение, поэтому всегда выполняйте проверку.DateTimeявляется изменяемым.modify()мутирует оригинал; используйтеDateTimeImmutable, чтобы избежать проблем с разделяемым состоянием.- Метки времени — это секунды UTC. При форматировании через
date()применяется текущий часовой пояс, поэтому одно и то же целое число отображается по-разному в зависимости от настроек.
Заключение
PHP предоставляет процедурный инструментарий для работы с метками времени (date(), time(), strtotime(), mktime()) и объектно-ориентированный (DateTime, DateTimeImmutable). Полагайтесь на обычные метки времени для простого отображения и хранения, а на DateTimeImmutable — для арифметики и логики с учётом часовых поясов. Для более детального изучения см. Дата и время в PHP, справочник date(), strtotime() и mktime().