Остановите перевод времени Django в UTC - PullRequest
3 голосов
/ 09 апреля 2019

Часовые пояса сводят меня с ума. Каждый раз, когда я думаю, что понял это, кто-то меняет часы, и я получаю дюжину ошибок. Я думаю, что наконец-то дошел до того, что я сохраняю правильное значение. Мои времена timestamp with time zone, и я не убираю часовой пояс, пока они не были спасены.

TIME_ZONE = 'Europe/London'
USE_I18N = USE_L10N = USE_TZ = True

Вот конкретное значение от Postgres до dbshell:

=> select start from bookings_booking where id = 280825;
2019-04-09 11:50:00+01

Но вот та же запись через shell_plus

Booking.objects.get(pk=280825).start
datetime.datetime(2019, 4, 9, 10, 50, tzinfo=<UTC>)

ДАММИТ ДЖАНГО, ЭТО НЕ БЫЛО ВРЕМЯ!

Эти времена работают отлично в шаблонах / admin / etc, но когда я генерирую отчеты в формате PDF и электронных таблиц, все идет не так, как надо, и мне внезапно приходится перераспределять время вручную. Я не понимаю, почему я должен это делать. Данные локализованы. Что происходит между запросом к базе данных и получением данных?

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

1 Ответ

2 голосов
/ 09 апреля 2019

Вы неверно истолковали это. База данных хранит время UTC большую часть времени. Если вы используете PostgreSQL, база данных может хранить время с информацией о часовом поясе, но для практических целей (*) проще всего думать, что время в вашей базе данных хранится как UTC (т.е. как абсолютное время, которое можно преобразовать в любое время зона), когда USE_TZ = True. Он всегда представляет собой правильный момент времени, для которого вам не нужно запоминать или предполагать какой-либо часовой пояс. И, насколько я знаю, Django всегда будет хранить время с учетом времени в часовом поясе UTC.

Таким образом, когда вы выбираете объект времени с помощью select в psql , вы возвращаете время в местном часовом поясе вашего компьютера (часовом поясе, в котором вы запускаете psql). Если кто-то из «America / New_York» выполнит тот же запрос выбора, он увидит отметку времени -04. Если бы дата была 2019-03-20, вы бы увидели 2019-03-20 10:50:00+00, потому что на эту дату Европа / Лондон и UTC были одинаковыми.

При извлечении значения DateTimeField как объекта Python datetime.datetime, Django всегда извлекает значение UTC, потому что:

Работа с осведомленными объектами даты и времени не всегда интуитивно понятна. За Например, аргумент tzinfo стандартного конструктора datetime не работает надежно для часовых поясов с DST. Использование UTC обычно безопасный; если вы используете другие часовые пояса, вы должны просмотреть pytz Документация тщательно.

Это облегчает работу с этими объектами datetime в вашем коде python: они всегда в формате UTC.

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

from django.utils import timezone
print(timezone.template_localtime(Booking.objects.get(pk=280825).start))

Отображает дату и время в часовом поясе по умолчанию (или, если вы activate() другой часовой пояс, в текущем часовом поясе ).

(*) Примечание: почему вы не должны придавать никакого значения часовому поясу, сохраненному в вашей БД, и просто думать об этом, как будто это все UTC: если бы вы запускали серверы в разных часовых поясах, вы могли бы на самом деле сохранить временные метки в разных часовых поясах. Они все еще правильные (абсолютные метки времени) и могут быть преобразованы в любой другой часовой пояс. Так что в основном часовой пояс, используемый для сохранения, не имеет смысла.

...