Вопрос-Ответ

Weird timezone issue with pytz

Странная проблема с часовым поясом в pytz
>>> import pytz
>>> pytz.timezone('Asia/Hong_Kong')
<DstTzInfo 'Asia/Hong_Kong' LMT+7:37:00 STD>

Смещение на семь часов и 37 минут? Это немного странно, кто-нибудь сталкивался с такой же проблемой?

На самом деле я получаю разное поведение между

import pytz
from datetime import datetime
hk = pytz.timezone('Asia/Hong_Kong')

dt1 = datetime(2012,1,1,tzinfo=hk)
dt2 = hk.localize(datetime(2012,1,1))
if dt1 > dt2:
print "Why?"
Переведено автоматически
Ответ 1

Часовые пояса и смещения меняются с годами. Имя зоны по умолчанию и смещение, предоставляемые при создании pytz объекта timezone, являются самыми ранними из доступных для этой зоны, и иногда они могут показаться странными. Когда вы используете localize для привязки зоны к дате, заменяются правильное название зоны и смещение. Простое использование datetime конструктора для привязки зоны к дате не позволяет ее корректно настроить.

Ответ 2

Придя сюда почти 10 лет спустя, я думаю, стоит отметить, что теперь мы можем использовать исключительно стандартную библиотеку Python 3.9+ для обработки часовых поясов без "ловушки локализации".

Используйте модуль zoneinfo для установки и замены tzinfo так, как вам нравится, например:

from datetime import datetime
from zoneinfo import ZoneInfo

hk = ZoneInfo('Asia/Hong_Kong')
print(repr(hk))
# zoneinfo.ZoneInfo(key='Asia/Hong_Kong')

dt1 = datetime(2012,1,1,tzinfo=hk)
print(dt1)
# 2012-01-01 00:00:00+08:00

Альтернативы, если вы не можете использовать zoneinfo:


  • для Python < 3.9 есть backports.zoneinfo

  • вы также могли бы использовать dateutil, который следует той же семантике, что и zoneinfo

Примечание для pandas пользователей:

Ответ 3

Хотя я уверен, что исторические изменения в часовых поясах являются фактором, передача объекта pytz timezone конструктору DateTime приводит к странному поведению даже для часовых поясов, которые не претерпевали изменений с момента их создания.

import datetime
import pytz

dt = datetime.datetime(2020, 7, 15, 0, 0, tzinfo= pytz.timezone('US/Eastern'))

выдает

2020-07-15 00:00:00-04:56

Создание объекта datetime с последующей его локализацией дало ожидаемые результаты

import datetime
import pytz

dt = datetime.datetime(2020, 7, 15, 0, 0)
dt_local = timezone('US/Eastern').localize(dt)

выдает

2020-07-15 00:00:00-04:00
2023-04-24 12:11 python datetime