February 20th, 2018

VR

О датах

Запишем даты в список проклятых тем в этом вашем вайти в которые никто не умеет. У всех с этими датами, временем, таймзонами выходит какая-то херня из-за чего всё едет к чертям и не работает.

Начать нужно с того что даты бывают разные и сильно зависят от контекста в котором их используют. Новый год в любой точке глобуса наступает 1 января, и в Владивостоке, и в Мариуполе, и в Нью-Йорке. Будильник настроенный на 9 утра должен звонить в 9 утра независимо от текущего местоположения. Но разговор по телефону назначенный на 9 утра в NY, в Киеве случится в 16 часов. Улавливаете мякотку?

Что делать, спросит читатель. Самое лучшее и универсальное решение: валить нафиг с этого вашего вайти. Сантехник, электрик, автомеханик, бариста на худой конец - пусть с датами разбирается кто-то другой. Решение похуже - забить. 83% разработчиков никогда в жизни не задумаются о таких сложных вопросах и у них всё будет работать. Не всегда правда, но то уже мелочи. Самое плохое решение - вот о нём и поговорим.

Я озвучу свой частный случай, ибо полного и универсального решения у меня нет, но думаю что оно и не надо. И так: сохраняйте контекст. Не обязательно в базе, можно (и наверное лучше), в ТЗ и сопроводительной документации. Нужно чётко понимать какие даты следуют за таймзонами, какие нет. При этом выбирайте правильные типы, дата это собирательное название для собсна даты, времени и даты с временем. При этом внезапно может оказаться что указывать нужно только дату, но при этом она должна ходить за таймзонами (как?). Что делать в коде: я не придумал ничего умнее чем написать кастомный материалайзер для EF6 и просто расставлять kind для дат на основании вручную проставленых атрибутов (метапрограммирование убер алес). Для тех кто ходит за таймзонами - UTC (они и в базе храняться как UTC). Для фиксированных - Local (в базе по хорошему хранить как date, time, datetimeoffset, но реальность вы и без меня знаете). Ещё написал свой конвертер в json, соответственно даты в UTC сериализуются с указанием таймзоны 'Z', даты в Local идут без таймзоны (почему-то Newtonsoft.Json так не умеет из коробки). В итоге на сайте они отображаются правильно, первые автомагически переводятся в таймзону клиента, вторые нет. Какие ещё есть подводные камни - вычисление интервалов. Часть дат у вас в UTC, часть фиксированы, это нужно помнить и учитывать. Ещё момент - входящие данные. Пользователь что-то ввёл - опять же не забывать правильно трактовать (наверное проще сделать через атрибуты и json converter, хотя хз, я на этот момент забил).

Да хранят вас боги времени :)

PS Никому электрик не нужен?