Работа с датой и временем в PHP
Невозможно стать разработчиком без знаний о манипуляциях с датой и временем. Хотите вы того или нет, но вы должны понимать временные метки, часовые пояса, UTC и стандарт ISO 8601. Ниже я расскажу об основах, начиная с теории, а затем переходя к практическим примерам.
1970–01–01 00:00:00
Временная метка Unix - это представление времени в формате big int в процессе разработки. Это количество секунд, прошедшее с 00:00:00 1 января 1970 года. Также вы можете найти, что она также называется Эпохой или временем POSIX. Итак, вот пример:
/* Наша дата */
'Monday, July 15, 2024 12:00:00 AM'
/* Unix timestamp */
1721001600
Такой подход позволяет нам максимально просто стандартизировать дату и время. Кроме того, целые числа очень удобны для сравнения.
Часовые пояса
UTC (Coordinated Universal Time в переводе означает "Всемирное координированное время") - это стандарт времени и основная точка отсчета для часовых поясов по всему миру. Нулевая точка смещения часовых поясов. UTC не соответствует переходу на летнее время.
Часовой пояс - это местное время, измененное с UTC в зависимости от географического положения. Количество часовых поясов увеличивается от Лондона к востоку. Например, в Лондоне время UTC+01:00, а в Екатеринбурге - UTC+05:00.
Вы можете установить часовой пояс по умолчанию для проекта, используя функцию date_default_time_zone(). Список часовых поясов приведен на сайте документации PHP.
date_default_timezone_set('America/Los_Angeles');
echo date('H:i:s') . PHP_EOL;
// 00:00:00
date_default_timezone_set('Asia/Yekaterinburg');
echo date('H:i:s') . PHP_EOL;
// 12:00:00
Позаботьтесь о часовых поясах в PHP, базе данных и сервере. Также учитывайте влияние перехода на летнее время на вашу разработку. Это может быть непросто, когда у вас есть несколько ежедневных процессов, связанных с выполнением сроков.
Функции PHP
// получить текущий unix timestamp
time();
// преобразование строки со временем и датой в unix timestamp
strtotime('Monday, July 15, 2024 12:00:00 AM');
// 1721001600
Date() — основная функция php. Основная, потому что это самый простой способ преобразовать дату и время в требуемый формат. Далее я опишу класс DateTime, но это уже другой случай.
date(
'Y-m-d H:i:s', // Формат MySQL DATETIME
strtotime('Monday, July 15, 2024 12:00:00 AM')
); // 2024-07-15 12:00:00
Эта функция преобразует int timestamp в форматированную строку. Более подробная информация здесь и доступные форматы здесь. На самом деле вы можете создать любой формат, какой пожелаете, просто выясните, что представляет собой каждый символ.
Форматы
Полные дата и время: Y-m-d H:i:s. Это базовый формат, который используется практически повсеместно для представления даты и времени. Так что, если вам нужна только дата, вы можете выбрать Y-m-d, если вам нужно время используйте H:i:s.
echo date('Y-m-d H:i:s');
// 2024-07-14 15:30:45
12-часовой формат с AM/PM: h:i:s A
echo date('h:i:s A');
// 03:30:45 PM
Дата ISO 8601: c
echo date('c');
// 2024-07-14T15:30:45+05:00
Американский формат дат m/d/Y может немного сбивать с толку, поскольку он используется только в Соединенных Штатах. Сначала указывается месяц, затем день и затем год.
echo date('m/d/Y');
// 07/15/2024
Более подробно можно узнать о мировых форматах в статье из Википедии.
Класс DateTime
Лучше официальной документации PHP не объяснить, рекомендую ознакомиться со специальной статьей: Представление даты и времени. Этот класс является мощным инструментом для работы с датой и временем.
С его помощью вы можете менять часовой пояс, устанавливать интервалы, анализировать различные (более сложные, чем может обработать strtotime) форматы даты и времени, сравнивать объекты datetime.
$nextDate = new DateTime('2024-07-15');
$endDate = new DateTime('2024-07-19');
// weekday это интервал с Mon - Fri (Пн - Пт)
$interval = DateInterval::createFromDateString('1 weekday');
// сравнение 2х объектов datetime
while ($nextDate < $endDate) {
// добавляем интервал и изменяем $nextDate
$nextDate->add($interval);
// тот же принцип, что и у функции date()
echo $nextDate->format('Y-m-d') . PHP_EOL;
}
// Вывод:
// 2024-07-16
// 2024-07-17
// 2024-07-18
// 2024-07-19
Carbon/Carbon
Это базовая библиотека для представления даты и времени в самых популярных фреймворках, таких как Laravel и Symfony. Вы можете установить ее в проекты, которые не используют фреймворк. Composer по-прежнему требуется. Документация: https://carbon.nesbot.com/docs/.
Тот же пример, что и выше, но теперь с использованием библиотеки Carbon. В этом формате код намного удобнее для чтения.
use Carbon\Carbon;
$nextDate = Carbon::parse('2024-02-07');
$endDate = Carbon::parse('2024-02-14');
while ($nextDate->lessThan($endDate)) {
$nextDate->addDay();
// Пропуск выходных
if (!$nextDate->isWeekend()) {
echo $nextDate->format('Y-m-d') . PHP_EOL;
}
}
// Вывод:
// 2024-02-08
// 2024-02-09 (Пропущен так как это выходной)
// 2024-02-10 (Аналогично)
// 2024-02-11
// 2024-02-12
// 2024-02-13
// 2024-02-14
Методы работы с базами данных
Существует 2 типа хранения времени в базах данных: с указанием часового пояса и без него. Рассмотрим примеры типов данных MySQL.
DATETIME:
- Представляет дату и время без какой-либо привязки к часовому поясу.
- Диапазон: с 1000-01-01 00:00:00 до 9999-12-31 23:59:59. Это строка вместо даты и времени.
TIMESTAMP:
- Хранит данные в формате UTC.
- Диапазон значений: с 1970-01-01 00:00:01 по 2038-01-19 03:14:07 (UTC) для 32-разрядных систем. Unix Timestamp
- Идеально подходит для хранения моментов времени (created_at, processed_at, finished_at, ...).
Такие же типы существуют и в других базах данных. Как, например, в PostgreSQL: TIMESTAMP и TIMESTAMP WITH TIME ZONE
Timestamp как boolean
На практике вы могли бы создать поле базы данных с именем started_at. Это поле может иметь значение null, что означает, что в нем хранятся дата и время запуска определенного процесса, а также указывается, действительно ли процесс запущен (если поле не равно null). Такие поля распространены в таких фреймворках, как Laravel, например, при реализации мягкого удаления с помощью поля deleted_at.
REST API
Почти все уважающие себя API используют формат ISO 8601. Пример: 2024-02-14T00:00:01Z. Также придерживайтесь часового пояса UTC, чтобы избежать путаницы с часовыми поясами.
$date = new DateTime('Monday, July 15, 2024 12:00:00 AM');
echo $date->format(DateTime::ISO8601) . PHP_EOL;
// 2024-07-15T00:00:00+0000
Я надеюсь, что эти основные сведения окажутся для вас полезными. Будьте внимательны и не забывайте использовать часовой пояс UTC!
Комментарии
Для того чтобы оставить свое мнение, необходимо зарегистрироваться на сайте