Сравнение времени в UTC с временем в восточном времени с использованием Python

Я пытаюсь сравнить два раза с помощью модуля Python datetime, но я не могу создать объект time с часовым поясом в UTC.

>>> import pytz, datetime
>>> UTC_TZ = pytz.utc
>>> EASTERN_TZ = pytz.timezone('America/New_York')
>>> d1 = datetime.time(10, tzinfo = UTC_TZ)
>>> d1
datetime.time(10, 0, tzinfo=<UTC>)
>>> d2 = datetime.time(10, tzinfo = EASTERN_TZ)
>>> d2
datetime.time(10, 0, tzinfo=<DstTzInfo 'America/New_York' EST-1 day, 19:00:00 STD>)
>>> d1 < d2
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: can't compare offset-naive and offset-aware times

Это ошибка? Есть ли специальный часовой пояс UTC, который мне нужно использовать? Что происходит?

Ответ 1

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

В соответствии с документами datetime, при сравнении двух объектов datetime.time: "Если оба сопоставления осведомлены и имеют разные атрибуты tzinfo, сравнения сначала корректируются путем вычитания их смещений UTC (полученных из self.utcoffset())"

В примере, который вы дали, сравнение вызывает TypeError, потому что EASTERN_TZ.utcoffset() возвращает None. utcoffset не является ничем, потому что восточные США отмечают время перехода на летнее время, и поэтому смещение по времени от UTC зависит от даты, которая недоступна в datetime.time.

Вы должны использовать объекты datetime.datetime для сопоставлений между часовыми поясами:

>>> import pytz, datetime
>>> UTC_TZ = pytz.utc
>>> EASTERN_TZ = pytz.timezone('America/New_York')
>>> d1 = datetime.datetime(2012, 1, 1, 10, 0, tzinfo=UTC_TZ)
>>> d2 = datetime.datetime(2012, 1, 1, 10, 0, tzinfo=EASTERN_TZ)
>>> d1 < d2
True

Ответ 2

Вы получаете ошибку, потому что пытаетесь измерить разницу между одним объектом time, который может быть привязан к определенному моменту UTC, а другой time объект, который является "наивным" и не может быть привязан к конкретному моменту UTC, Исправление состоит в том, чтобы сделать оба сопоставления смещенными или обеими наивными.

Ниже используются объекты datetime, но в основном такая же идея.

import datetime, time, pytz

EST = pytz.timezone('America/New_York')
UTC = pytz.timezone('Etc/UTC')
dt1 = datetime.datetime.fromtimestamp(time.time(), EST)
# ... time passes
dt2 = datetime.datetime.fromtimestamp(time.time(), UTC)
elapsed = dt2 - dt1

Ответ 3

Я предполагаю, что проблема в том, что UTC считается не-часовым поясом или "смещенным-наивным", возможно? Я бы рекомендовал преобразовать все в UTC, прежде чем делать какие-либо сравнения.

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

Кроме того, вы не должны этого делать. Лучше использовать

timezone.localize(dt)

как описано здесь: http://pytz.sourceforge.net/#localized-times-and-date-arithmetic