top of page

Дата-время, таймзоны...

  • Фото автора: Алик Ким
    Алик Ким
  • 21 дек. 2022 г.
  • 3 мин. чтения

Обновлено: 28 апр. 2023 г.

поизучал немного эту тему.

общее впечатление: даты-время - очень опасная штука под крайне невинной оболочкой. надо ж, никогда особо не задумывался об этом. если пишешь международное приложение - с этими тварями нужно обращаться крайне осторожно.


https://apiux.com/2013/03/20/5-laws-api-dates-and-times/ - полезная статья с рекомендациями. принципы работы с датами, согласно этой статье:

  • Use ISO-8601 for your dates //это - строки вида "2022-01-13T16:25:35.1250000+06:00" - дата-время + смещение относительно UTC-0, с учетом которого это время и задано.

  • Accept any timezone

  • Store it in UTC

  • Return it in UTC

  • Don’t use time if you don’t need it


но аргументация в последнем совете слабовата: если даже отправить дату в UTC без указания времени (то есть, если это будет UTC-полночь) - это не убережет наше значение от изменения даты при преобразовании в локальное время. например, если преобразовать UTC-полночь в UTC-08 - получится 16:00 предыдущего дня.


ну и ,вот, пример, когда нам нужны только даты, без времени: менеджер какого-нибудь работающего по всему миру интернет-магазина, находясь в Алмаате (UTC+6), захочет посмотреть все продажи, сделанные за вчера - по сути он ожидает увидеть продажи начиная с 6 утра по гринвичу за вчерашний день и по 6 утра по гринвичу сегодняшнего дня.

то есть для того, чтоб отфильтровать продажи правильно - нужно с клиента (допустим, это - браузер/джаваскрипт) отправить дату-время, соответствующую полуночи для обеих дат диапазона.

по факту это время соответствует 6 утра по гринвичу.

а так как даты в БД у нас по-хорошему хранятся тоже в UTC0-виде - все должно отфильроваться без проблем, будут найдены просто продажи между 6 утра UTC0 за вчера и за сегодня.

а вот при отсечении временнОй части из значений даты-времени - начались бы проблемы, потому что часовой пояс у сервера может не сответствовать часовому поясу клиента, а, значит, как определить, в какой момент для клиента наступает новая дата... и пошло-поехало.



ну а когда пишешь приложение, которое будет использоваться в рамках одного региона/таймзоны - все ужасы ночи исчезают, все становится просто и привычно, дата - один из простых типов данных вроде целого числа или строки🙂



а, еще нюанс/к размышлению (об этом пишется в этой статье): может быть дата/время, не привязанное к определенной точке на шкале истории. приводятся примеры: момент начала праздника 14 февраля - в каждой таймзоне он свой. или какое время считать слишком ранним (для звонка, например). статья - про JS, поэтому тут советуют такие ситуации разруливать на строках.

а мне вот тут на ум, как раз, пришел DateTime.Kind = Unspecified (см. ниже), может, он - как раз, для таких случаев



C#:

DateTime.Now - создает дату-время с местным UTC. чтоб привести к UTC0 - ToUniversalTime()


как преобразовать дату-время в другую таймзону: TimeZoneInfo.ConvertTime(dt, TimeZoneInfo.FindSystemTimeZoneById("Central Standard Time"));

где "Central Standard Time": в системе есть список таймзон - вот это - значение ИД такой таймзоны. вот тут они: https://howtomanagedevices.com/windows-10/1774/list-of-windows-10-time-zone-codes-tzutil/

*кстати, вот интересно: а в Linux же свой набор таймзон, наверное? как-то это не очень хорошо для кроссплатформенности... ну уже не стал разбираться.


обращаю внимание: "таймзона" не равно "смещение": в одной таймзоне в разное время года может быть разное смещение относительно UTC0 засчет перехода на зимнее/летнее время


TimeZoneInfo.ConvertTimeToUtc - конвертация в UTC


у DateTime есть свойство Kind. его возможные значения: Local, Utc и Unspecified.

его можно поменять вручную, тогда у даты-времени сменится смещение, а значение, собственно, времени, останется тем же.

в целом нет причин так делать, наверное.


вот так можно получить ISO-8601-строку:

DateTime.ToString("o")




Javascript:

тут дается расклад

new Date().toISOString() - преобразует в строку ISO-8601, при чем, конвертит в UTC-0

объекты Date всегда хранят дату-время в UTC0. но все методы приводят к текущей таймзоне. кроме специализированных , типа toISOString. еще, в частности, JSON.Stringify преобразует дату-время в UTC-строку


SQL Server:

есть тип данных datetimeoffset - как я понял, он предназначен для хранения даты-времени, включая смещение (ну , то есть, то же, что хранится в C#-DateTime)


API:

для API-вызовов нужно использовать ISO-8601. WebAPI прекрасно понимает этот формат.

нужно принимать в любых таймзонах, для хранения советуют преобразовывать в UTC-0


полезные ссылки:

https://apiux.com/2013/03/20/5-laws-api-dates-and-times/ - предлагаются принципы работы с датами

https://dba.stackexchange.com/questions/39421/how-to-handle-timezone-properly-in-sql-server - некоторые полезные рассуждения

https://www.ursahealth.com/new-insights/dates-and-timezones-in-javascript - расклад по датам-времени в JS + полезные рассуждения


 
 
 

Недавние посты

Смотреть все

Bình luận


Околокомпьютерный блог Алика

  • alt.text.label.Facebook

© Околокомпьютерный блог Алика , 2022. Сайт создан на Wix.com

bottom of page