Как стать автором
Обновить

Единый формат времени для приложения

Уровень сложностиСредний
Время на прочтение3 мин
Количество просмотров12K

Данная статья была написана мной при работе в компании. Будет полезна для понимания времени разработчикам и аналитикам, а также для организации контрактов как best practice. Как выяснилось на практике, далеко не все представляют себе часовые пояса в разработке.

Команда работала с фреймворком Angular, ввиду этого будет он и упомянут. Утверждения правдивы и для React/Vue/... в схожих кейсах.

Небольшой голоссарий:

  • пайп (pipe) в Angular - функция приобразования в шаблоне; стоит понимать как чистую функцию

  • TZ - time zone - часовой пояс

  • DRY - don't repeat yourself

Ввиду сильного раздрая и неясности работы frontend и backend с датами и временем, были вынесены на обсуждение следующие договоренности.

Очень рекомендую к прочтению: 

  1. Заблуждения программистов относительно времени

  2. Всемирное координированное время - что такое UTC, GMT

Утверждение

Обоснование

1. Общение фронта с бэком всегда в формате iso-string с указанием часового пояса в формате UTC (Z - метка нулевого часового пояса)

- время в базе данных (должно) хранится в UTC по 0 поясу (не важно это iso-string или timestamp)

- при получении даты с часовым поясом, отличным от 0, время, сохраняемое в базу, будет преобразовано к 0 часовому поясу

- единый формат и шкала измерения данных предупреждают ошибки

- UTC = международный, признанный формат данных

- международная космическая станция использует UTC в качестве эталона времени

2. Временные метки для данных везде где возможно брать на сервере, а не со стороны клиента

- время клиента далеко не всегда совпадает со временем сервера (имеется ввиду не часовой пояс UTC)

- время клиента не всегда правдиво (неправильное время)

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

Пример: "+180" = "+03:00" = TZ Москва

UPD: После комментариев сообщества считаю, что предпочтительнее будет использовать формат геопозиции (пример: "America/Toronto"). Это позволит избежать проблемы летнего времени. Минус - нужен синхронизированный словарь фронта и бэка, что в реальности не очень сложно.

- стандартный date pipe angular'а используют смещение для вывода данных

- позволяет соблюсти формат UTC при общении с сервером

Нужно уточнить формат смещения. Стандартно предполагается два варианта: 

- number ( смещение в часах "(+/-)  * 60")

- string (пример, Москва - "+03:00")

Формат типа string используется в смещении времени date pipe в виде как есть (пример: "timeVar | date: "DD:MM:YYYY HH:mm : "+03:00" => 01.01.2020 11:32; UTC - 01.01.2020 08:32).

4. На фронте оптимизировать правильный формат вывода данных в константу

Пример: "DD:MM:YYYY HH:mm"

- унификация и выполнения принципа DRY

5. Для преобразование времени на вывод использовать единый пайп

- унификация и выполнения принципа DRY

6. Использование единого формата iso-string (в UTC) по всему приложению при общении между сущностями

- единый формат и шкала измерения данных предупреждают ошибки

- перевод из iso-string в формат объекта данных просто написать самостоятельно или использовать библиотеку

- iso-string "кушают" все (обязательно нужно помнить про указание часового пояса)

Далее пример с использованием Angular (в целом будет понятен без знания)

  • Component - некая сущность с логикой (в примере - .ts файл)

  • Шаблон - html-файл, соединённый с Component

  • Интерполяция в Angular - механизм привязки переменной шаблона и логики (в примере: Component и шаблона; ссылка на определение)

  • FormControl - элемент Angular Forms; класс с методами set, get, подписки на измененные статусы и события и др.

Дано: 

  1. Компонент (Component) с шаблоном (html)

  2. Сервер (backend)

  3. formatVar = "DD.MM.YYYY HH:mm"

  4. offsetVar = время клиента "+03:00" (предположим что лежит на клиенте, может приходить с сервера в том же запросе)

Путь отображения без промежуточных звеньев:

  1. Component делает запрос на backend, приходит:

    • date: "2020-11-17T15:06:47.523Z" => переменная dateVar

  2. Component сохраняет данные в переменные

  3. В шаблоне (html) в блок (div) через интерполяцию вставляется переменная + angular date pipe

    • dateVar | date : formatVar : offsetVar (см. Дано)

    • вывод => 2020.11.17 18:06

  4. Пользователь меняет переменную dateVar на 2020.11.17 20:00

  5. Пользователь жмет "Сохранить"

  6. Component преобразует дату к формату iso-string (стоит уточнить условия на практике, т.к. на момент написания статьи были нюансы)

    • если из FormControl поступает iso-string с указанием часового пояса, то формат готов 

    • если из FormControl поступает string без часового пояса, то тут возможны варианты, но по факту все сведется к `new Date(var съедобного формата с часовым поясом).toISOstring()`

  7. Component отправляет данные на backend в формате iso-string с TZ

Теги:
Хабы:
Всего голосов 1: ↑1 и ↓0+1
Комментарии14

Публикации

Работа

Ближайшие события