Временные метки и таймзоны в Ensi
Общее описание
Большой проблемой при работе с datetime является обработка таймзон.
Когда во Владивостоке "2021-01-01 06:00", в Москве еще "2020-12-31 23:00".
Со временем смещения часовых поясов могут меняться, может вводиться и отменяться летнее время.
Общепринятые лучшие практики
Во всех backend-сервисах оперируем datetime в UTC, т.е
- Время в контейнерах в UTC
- В php.ini timezone = UTC
- В сервисах config('app.timezone') === UTC
- В базах datetime пишем как UTC без таймзоны (для Laravel-Postgres это автоматические решается предыдущим пунктом, дополнительно базу трогать не нужно)
- Время запуска кронов в UTC
Для передачи datetime через API и очереди используется формат ISO-8601. Время в нём тоже в UTC (буква Z) Например,
"updated_at": "2020-01-01T15:47:21.000000Z"
, Начиная с 7 версии Laravel автоматически приводит datetime в этот формат при конвертации модели в json.Конвертация UTC в нужную пользователю таймзону происходит уже в самый последний момент - на фронтенде, в момент показа времени. В какую именно таймзону конвертировать - вопрос бизнес логики. Иногда это может быть таймзона пользователя (можно получить из браузера), иногда таймзона события, иногда какая-то другая.
Аналогичным образом при получении инпута от пользователя он должен быть на фронте сконвертирован в UTC и отправиться в API уже в таком виде.
Коммуникация с пользователем (т.е показ ему datetime) может происходить не только через браузер, но и через письма, смс и прочее. Поэтому при регистрации пользователя необходимо сохранить его таймзону в базу и, желательно, дать возможность менять в профиле.