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

Комментарии 17

Если я правильно понимаю, осовная фича timestamptz заключается в том, что значение автоматически сохраняется в UTC в соответствии с текущим часовым поясом, и при запросах соответственно преобразуется обратно?

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

Не лучше-ли сохранять в базе UTC и делать преобразования ближе к front-end-у?
Мне кажется, тогда можно кешировать больше данных, так как на уровне базы данных и бизнес-логики можно работать в UTC, с однородными данными.
Да, в целом правильно, при условии что вы, принимая пользовательский input, явно указываете, в каком часовом поясе приняли время пользователя, опираясь на его настройки или определяя местоположение по IP, например. Иначе входное время будет некорректно интерпретироваться при конвертации.

Лично я склонен согласиться, что в такой ситуации UTC наиболее эффективен и устраняет много ненужных проблем. Но требуется аккуратность с вводом/выводом значений времени.

Более «ленивый» путь — это четко декларировать что ваш сервис / платформа работают по такому-то времени (будь-то Москва, UTC или что-то иное), и что все операции ввода/вывода времени происходят в этой таймзоне. Это складывает ответственность по учету времени на пользователя, но облегчает разработку и эксплуатацию системы.

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

Возможно, коллеги предложат сценарии, когда использование UTC в качестве основной настройки сервера СУБД нежелательно.
>Возможно, коллеги предложат сценарии, когда использование UTC в качестве основной настройки сервера СУБД нежелательно.

Я сходу не вспомню адрес, но тут же на Хабре была большая статья, затрагивающая эту проблему.
Суть в том, что для того, чтобы получить время в какой-то локальной временной зоне, надо иметь базу данных по смещению времени в прошлом и в будущем (!) на весь диапазон рассматриваемых времён. Как в UTC записать дату «через 6 месяцев в 10 часов МСК», если неизвестно, какое будет тогда смещение? Поэтому, в принципе, настройка самого сервера к этой проблеме отношения не имеет, это полезно только в смысле анализа логов. А время хранить в полях с временной зоной timestamp with time zone.

>И timestamp, и timestamptz (и другие виды данных, относящиеся ко времени) могут иметь дополнительную точность (“precision”).

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

Про эту говорите? habrahabr.ru/company/mailru/blog/242645
Хорошая статья, спасибо за ссылку.
> Суть в том, что для того, чтобы получить время в какой-то локальной временной зоне, надо иметь базу данных по смещению времени в прошлом и в будущем (!) на весь диапазон рассматриваемых времён. Как в UTC записать дату «через 6 месяцев в 10 часов МСК», если неизвестно, какое будет тогда смещение?

Иметь базу на будущее — в принципе невозможно. Мы же не можем предсказать, решит наше правительство осуществлять переход на зимнее/летнее время или нет. Нужный брать требуемый timestamptz at time zone и записывать, в приложении отображать at time zone «Europe/Moscow» и своевременно обновлять базы часовых поясов при внесении в них изменений.
Вот я и пишу — сохранять время в timestampz, как Вы рекомендуете, надо с большой осторожностью.

>Короче говоря, старайтесь избегать timestamp и используйте timestamptz.

Короче говоря, старайтесь избегать timestamp и timestamptz и используйте timestamp with time zone.

Крайний случай — когда ещё надо сохранять дополнительную информацию, а именно смещение так, как его считает правильнымм источник данных. Например, ДНР/ЛНР как часть украины имели одну временную зону, а как отдельное от Украины образование — другую. Основной принцип — не должна происходить потеря исходных данных.
Всё ж таки не хватает типа, в котором будет храниться кроме таймстампа ещё и часовая зона: и идентификатор и смещение. Для хранения времён в будущем это важно, чтобы ловить непредсказуемые изменения часовых зон.
Это палка о двух концах. Возможно, я не понимаю сценарий, когда необходимо хранить время в заведомо неправильной, относительно текущей действительности, таймзоне. Но в такой ситуации, если вы запишите уйму меток в формате «timestamp +03», например (для Московского времени), потом депутаты решат сделать перевод таймзоны, и у вас будет большая проблема с кучей таймстампов, не соответствующих действительности. Дело дойдет либо до усложнения бизнес-логики (вручную в приложении разруливать такие ситуации), либо до внесения изменений в БД для корректировки часового пояса. Я такие приключения наблюдал в крупном продакшене, это очень печально.
Я так понимаю, товарищ говорил о том, чтобы вместе с временем сохранять ID часового пояса (типа 1='America/Los_Angeles')
Тогда время может быть корректно рассчитано даже при изменении зимнего/летнего времени или часовых поясов.
И все равно проблема есть. Если у нас сохранено. «2010-01-01 15.00.00» utc и отдельно сохранено таймзона = 'Moskow' Что это нам дает?? Проблемы, учитывая, что в то время смещение Москвы от utc было не такое как сейчас!!!
Почему не такое?

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

Как правильно заметили выше, будущие даты возможно придется корректировать, особенно если в данной местности сменили сам часовой пояс. Но не прошлые даты (за крайне редким исключением баг фиксов в исторических часовых поясах — я видел пару таких случаев, вроде-бы).
У меня есть случай, когда время указывается с временной зоной «местное время». Вот где настоящий ад. Поэтому с указанием времени приходится хранить информацию об источнике времени.
Ну да, это как раз та самая настройка таймзоны у пользователя. Ее надо запрашивать явно или определять по местоположению.
Сценарий таков: сохраняем тройку значений: корректное время в будущем в UTC, оно же локальное (или смещение, не суть), идентификатор часовой зоны. Потом наша госдума доблестно переводит всю нашу страну (или часть) на час или два в какую-то сторону и перекраивает часть часовых поясов. Задача: после обновления tzdata найти те времена, которые «поехали» и исправить. Для каких-то таймстампов надо перемотать локальное время, для каких-то — время в UTC (если нам важно сохранить именно значение локального времени). Собственно, задача уже рассматривалась в этой статье, которую уже процитировали и тут и на фейсбуке: habrahabr.ru/company/mailru/blog/242645 и решение про тройку значений взято оттуда.
Да, вы правы, это хороший пример. Пожалуй, добавлю ссылку на эту статью в тело сообщения, для дополнительного изучения читателями.
Мы храним все даты в UTC, конвертируем вводные и выходные данные. Но есть вариант, когда надо работать с временными зонами на уровне самой базы — отчеты. Например график количества заказов по дням недели — границы дней недели зависит от временной зоны клиента.

Пока мы не кешируем статистику, но когда будем это делать, к ключу кеша надо будет добавлять временную зону клиента.
Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Истории