Когда происходит `datetime.now(pytz_timezone)`?
delorean
Документы показывают этот способ, чтобы получить текущее время в заданном часовом поясе, используя datetime
:
from datetime import datetime
from pytz import timezone
EST = "US/Eastern"
UTC = "UTC"
d = datetime.utcnow()
utc = timezone(UTC)
est = timezone(EST)
d = utc.localize(d)
d = est.normalize(EST)
и сравните его с кодом на основе delorian:
from delorean import Delorean
EST = "US/Eastern"
d = Delorean(timezone=EST)
Я верю datetime
Пример должен быть записан как:
from datetime import datetime
import pytz
eastern_timezone = pytz.timezone("US/Eastern")
d = datetime.now(eastern_timezone)
это более кратко.
Есть ли случаи, когда последний пример кода не работает, а первый продолжает работать?
Обновление: текущий пример:
from datetime import datetime
import pytz
d = datetime.utcnow()
d = pytz.utc.localize(d)
est = pytz.timezone('US/Eastern')
d = est.normalize(d)
return d
это все еще слишком многословно.
Вопрос все еще стоит: вам нужен явный туда-обратно через utc и tz.normalize()
или вы можете использовать datetime.now(tz)
вместо?
1 ответ
Когда делает
datetime.now(pytz_timezone)
потерпеть поражение?
Насколько я могу судить, нет сценариев, когда он мог бы потерпеть неудачу. datetime.now
вызывает fromutc
функция на tzinfo
экземпляр передан в параметре. Все преобразования из UTC в местное время однозначны, поэтому нет никаких шансов на провал.
Кроме того, оригинальный код даже не работает.
d = est.normalize(EST)
Казалось бы, передать строку в качестве единственного параметра normalize
, который предназначен для datetime
, Это дает:
AttributeError: 'str' object has no attribute 'tzinfo'
Я считаю, что они хотели написать:
d = est.normalize(d.astimezone(est))
Тем не менее, я не думаю, что многословие их кода добавляет много ценности. Как вы заметили, это так же легко сделать за один шаг:
d = datetime.now(est)
Глядя на исходный код cpython дляdatetime.now
Я вижу, что когда tzinfo
объект предоставляется, он вызывает fromutc
метод на этом объекте.
if (self != NULL && tz != Py_None) {
/* Convert UTC to tzinfo's zone. */
PyObject *temp = self;
self = _PyObject_CallMethodId(tz, &PyId_fromutc, "O", self);
Py_DECREF(temp);
}
Затем в источнике pytz я вижу, что fromutc
Метод реализуется по-разному в зависимости от того, является ли зона pytz.UTC
или экземпляр StaticTzInfo
, или же DstTzInfo
, Во всех трех случаях преобразование входного значения UTC в целевой часовой пояс является однозначным. Здесь DstTzInfo
реализация, которая является более сложной из трех:
def fromutc(self, dt):
'''See datetime.tzinfo.fromutc'''
if (dt.tzinfo is not None
and getattr(dt.tzinfo, '_tzinfos', None) is not self._tzinfos):
raise ValueError('fromutc: dt.tzinfo is not self')
dt = dt.replace(tzinfo=None)
idx = max(0, bisect_right(self._utc_transition_times, dt) - 1)
inf = self._transition_info[idx]
return (dt + inf[0]).replace(tzinfo=self._tzinfos[inf])
Это, казалось бы, найти переход от _utc_transition_times
часового пояса, затем примените его к datetime
, В этом направлении нет двусмысленности, поэтому результаты будут эквивалентны.
Также стоит отметить, что в datetime
документы это говорит о том, что datetime.now
эквивалентно звонку:
tz.fromutc(datetime.utcnow().replace(tzinfo=tz))
Учитывая источник fromutc
в pytz я показал ранее, я не уверен, что это отличается от просто:
tz.fromutc(datetime.utcnow())
Но в любом случае я не думаю, localize
а также normalize
необходимы.