Pull to refresh

Comments 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`ы и уже ездить с ноды на ноду, не думая, что что-то забудется.

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

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

Articles