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

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

Я не использую способ
sudo ln -sf /usr/share/zoneinfo/UTC /etc/localtime
, потому что при обновлении системы или пакета tzdata файл /etc/localtime у меня перезаписывался на значение по умолчанию, а файла /etc/timezone в используемых мной дистрибутивах нет.
В RedHat-подобных дистрибутивах рекомендуется такой алгоритм:

1. Изменить файл /etc/sysconfig/clock (создать его при необходимости):
ZONE="Europe/Kiev"
UTC=true

Здесь ZONE — часовая зона; все эти зоны находятся в каталоге /usr/share/zoneinfo/; UTC-идут ли внутренние часы компа по UTC(GMT) или по локальному времени (рекомендовано true (идут по GMT), но на компах с Виндой придётся ставить false)
2. Теперь запустить tzdata-update:
/usr/sbin/tzdata-update
я всегда использую datetime:
1. юзерскую дату конвертирую в UTC
2. сохраняю в БД
3. отображаю в зависимости от зоны юзера
и никаких проблем с переездами по зонам не бывает
В вашем подходе безусловно есть плюс, т.к. диапазон значений TIMESTAMP сильно ограничен, в отличие от DATETIME.

Но проблемы могут возникнуть при «переезде» сервера из одной зоны в другую. В статье есть пример, когда при разворачивании базы на другом сервере с настроенной зоной не на UTC (опустим причины, по которым это может произойти) могут возникнуть проблемы после конвертации значений DATETIME в unix-эпохи как на стороне базы, так и при работе с C-функциями.
В данном случае мы не зависим от текущей зоны, мы просто знаем что все значения в UTC, и можем конвертировать в любую таймзону (на уровне приложения, а не БД), т.е. получаем преимущества TIMESTAMP и DATETIME. Или же я не правильно Вас понял.
Согласен с вами. В связи с вашим комментарием сделаю дополнение:

В смысле значений мы не зависим. Но давайте рассмотрим пример:

— сначала вы берете эти данные из БД. Можно взять в виде «строки» или в виде unix-эпох (бывает, что ORM делает это за вас). Если вы выбираете в виде эпох, и сессионная зона подключения отличается от зоны, в которой создавалась запись, то результат будет другой. Если вы взяли значение в виде строки, то эту строку нужно парсить, чтобы скорректировать значение для пользовательской зоны.

— теперь мы имеем в нашей программе дату, которую можно сконвертировать в пользовательское время. Для этого можно воспользоваться C-функциями и, чтобы не зависеть от настроек зоны в системе, лучше пользоваться timegm.
и сессионная зона подключения отличается от зоны, в которой создавалась запись

А разве нам важно из какой зоны создавалась запись, если мы храним ее в UTC? Единственное условие, при переезде с сервера на сервер, всегда ставить UTC в настройках подключения к БД, а если мы используем только DATETIME, даже этого не придется делать.
Единственное правильное — просто следить чтобы при любых операциях над БД и прочих манипуляциях (до отображения юзеру) время было в UTC. И всё, все перечисленные проблемы не будут существовать как класс при любых реформах и переездах серверов.

з.ы.
Общая рекомендация по sqlite: храните дату в виде целого числа (integer), в который уже включены leap seconds (как в mysql). Тогда вы всегда будете знать точное время.
Это в какой это integer включены leap seconds? Простой timestamp? Вы что-то путаете, туда она не может быть по определению включена.
Ещё один способ — настраивать сервер один раз и качественно. Использовать puppet/chef`ы и уже ездить с ноды на ноду, не думая, что что-то забудется.

Ручное конфигурирование — наследие средних веков.

А аргумент типа «что-то забудете» это уже как-то странно — из-за того, что мы забывчивы в админстве и не умеем записывать мы тратим лишнее время на приведение системы в определённую идеологию на программерском уровне. Оно нам надо?
Ну, по закону с не очень давнего времени именно это является официальным названием в РФ.
Вообще-то «часовые зоны». Но ОК.
Да, спутал, сорри)
Офтоп. Кто же покажет данную статью ребятам из майкрософт, когда же они скайп починят. Достали эти сообщения из прошлого…
Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Истории