Перейти к основному содержимому

Временные метки и таймзоны в Ensi

Общее описание

Большой проблемой при работе с datetime является обработка таймзон.

Когда во Владивостоке "2021-01-01 06:00", в Москве еще "2020-12-31 23:00".

Со временем смещения часовых поясов могут меняться, может вводиться и отменяться летнее время.

Общепринятые лучшие практики

  1. Во всех backend-сервисах оперируем datetime в UTC, т.е

    • Время в контейнерах в UTC
    • В php.ini timezone = UTC
    • В сервисах config('app.timezone') === UTC
    • В базах datetime пишем как UTC без таймзоны (для Laravel-Postgres это автоматические решается предыдущим пунктом, дополнительно базу трогать не нужно)
    • Время запуска кронов в UTC
  2. Для передачи datetime через API и очереди используется формат ISO-8601. Время в нём тоже в UTC (буква Z) Например, "updated_at": "2020-01-01T15:47:21.000000Z", Начиная с 7 версии Laravel автоматически приводит datetime в этот формат при конвертации модели в json.

  3. Конвертация UTC в нужную пользователю таймзону происходит уже в самый последний момент - на фронтенде, в момент показа времени. В какую именно таймзону конвертировать - вопрос бизнес логики. Иногда это может быть таймзона пользователя (можно получить из браузера), иногда таймзона события, иногда какая-то другая.

  4. Аналогичным образом при получении инпута от пользователя он должен быть на фронте сконвертирован в UTC и отправиться в API уже в таком виде.

  5. Коммуникация с пользователем (т.е показ ему datetime) может происходить не только через браузер, но и через письма, смс и прочее. Поэтому при регистрации пользователя необходимо сохранить его таймзону в базу и, желательно, дать возможность менять в профиле.