Python pytz本地化与日期时间替换

Python pytz本地化与日期时间替换,python,datetime,timezone,utc,pytz,Python,Datetime,Timezone,Utc,Pytz,pytz的.localize()函数有一些奇怪的问题。有时它不会对本地化日期时间进行调整: .本地化行为: >>> tz <DstTzInfo 'Africa/Abidjan' LMT-1 day, 23:44:00 STD> >>> d datetime.datetime(2009, 9, 2, 14, 45, 42, 91421) >>> tz.localize(d) datetime.datetime(2009, 9,

pytz的.localize()函数有一些奇怪的问题。有时它不会对本地化日期时间进行调整:

.本地化行为:

>>> tz
<DstTzInfo 'Africa/Abidjan' LMT-1 day, 23:44:00 STD> 
>>> d
datetime.datetime(2009, 9, 2, 14, 45, 42, 91421)

>>> tz.localize(d)
datetime.datetime(2009, 9, 2, 14, 45, 42, 91421, 
                  tzinfo=<DstTzInfo 'Africa/Abidjan' GMT0:00:00 STD>)
>>> tz.normalize(tz.localize(d))
datetime.datetime(2009, 9, 2, 14, 45, 42, 91421,
                  tzinfo=<DstTzInfo 'Africa/Abidjan' GMT0:00:00 STD>)
>>tz
>>>d
datetime.datetime(2009,9,2,14,45,4291421)
>>>tz.本地化(d)
datetime.datetime(2009,9,2,14,45,4291421,
tzinfo=)
>>>z.规范化(z.本地化(d))
datetime.datetime(2009,9,2,14,45,4291421,
tzinfo=)
正如您所看到的,时间并没有因为本地化/规范化操作而改变。 但是,如果使用.replace:

>>> d.replace(tzinfo=tz)
datetime.datetime(2009, 9, 2, 14, 45, 42, 91421, 
                  tzinfo=<DstTzInfo 'Africa/Abidjan' LMT-1 day, 23:44:00 STD>)
>>> tz.normalize(d.replace(tzinfo=tz))
datetime.datetime(2009, 9, 2, 15, 1, 42, 91421,
                  tzinfo=<DstTzInfo 'Africa/Abidjan' GMT0:00:00 STD>)
>>d.replace(tzinfo=tz)
datetime.datetime(2009,9,2,14,45,4291421,
tzinfo=)
>>>tz.标准化(d.替换(tzinfo=tz))
datetime.datetime(2009,9,2,15,1,42,91421,
tzinfo=)
这似乎对datetime进行了调整


问题是-哪一个是正确的,为什么其他人错了?

localize
只是假设您传递的原始日期时间是“正确的”(除了不知道时区!),所以只设置时区,没有其他调整


当您需要以本地化方式执行日期时间的I/O时,您可以(并且建议…)在UTC内部工作(而不是使用原始日期时间),并使用
替换
规范化
将处理DST等)。

此DstTzInfo类用于UTC偏移在某些时间点发生变化的时区。例如(您可能知道),许多地点在夏初过渡到“夏令时”,然后在夏末回到“标准时间”。每个DSTZINFO实例仅代表其中一个时区,但“本地化”和“规范化”方法可帮助您获得正确的实例

对阿比让来说,只有一次过渡(根据pytz的说法),那是在1912年:

>>> tz = pytz.timezone('Africa/Abidjan')
>>> tz._utc_transition_times
[datetime.datetime(1, 1, 1, 0, 0), datetime.datetime(1912, 1, 1, 0, 16, 8)]
我们从pytz中得到的tz对象表示1912年以前的时区:

>>> tz
<DstTzInfo 'Africa/Abidjan' LMT-1 day, 23:44:00 STD>
>>tz
现在看看您的两个示例,当您调用tz.localize(d)时,您不会将这个1912年以前的时区添加到您的原始datetime对象中。它假定您提供给它的datetime对象表示该本地时间的正确时区中的本地时间,即1912年后的时区


但是,在使用d.replace(tzinfo=tz)的第二个示例中,它使用datetime对象来表示1912年以前时区中的时间。这可能不是你的意思。然后,当您调用dt.normalize时,它会将其转换为适合该日期时间值的时区,即1912年后的时区。

我意识到我在这方面有点晚了。。。 但以下是我发现效果很好的方法。 如Alex所述,在UTC工作:

tz = pytz.timezone('Africa/Abidjan')
now = datetime.datetime.utcnow()
然后本地化:

tzoffset = tz.utcoffset(now)
mynow = now+tzoffset

这种方法确实可以完美地处理DST

本地化
是用于创建具有初始固定日期时间值的日期时间感知对象的正确函数。生成的datetime感知对象将具有原始datetime值。在我看来,这是一种非常常见的使用模式,也许pytz可以更好地记录它


replace(tzinfo=…)
的名称很不幸。它是一个行为随机的函数。我建议避免使用这个功能来设置时区,除非你喜欢自己造成的痛苦。我已经受够了使用此功能的痛苦。

请引用Alex的话,了解在I/O操作期间使用UTC和本地化/非本地化的建议。请允许我建议,这是不可取的,但强烈建议(请阅读!OP询问了
本地化
替换
之间的区别。
replace
是否也只设置时区,不进行其他调整?如果是这样,为什么这两个结果之间存在差异?@MichaelWaterfall:
pytz.timezone()
可能对应于多个tzinfo对象(相同的位置、不同的UTC偏移、时区缩写)
tz.localize(d)
尝试为给定的
d
本地时间(某些本地时间不明确或不存在)找到正确的tzinfo
replace()
只设置pytz时区默认提供的任何(随机)信息,而不考虑给定日期(最新版本中的LMT)<如果
d
是不存在的本地时间,例如春季(北半球)DST转换期间的时间,则code>tz.normalize()
可以调整时间,否则在这种情况下它不会做任何事情。
replace(tzinfo=…)
因此似乎没有用。最好避免这种情况。如果
.utcoffset()
方法期望本地时区中的日期时间与utc不同,则这是不正确的。要获取本地时区中的当前时间:
now=datetime.now(tz)
。要将utc时间转换为本地时区:
dt=utc\u dt.replace(tzinfo=pytz.utc).astimezone(tz)
(您不需要
.localize()
.normalize()
)此处)。如果偏移量跨越DST边界,也可能不正确。相关:无法对此提出异议。完全同意。现在处理replace()完全不起作用但不会引发错误的问题。什么都不做。需要一种更好的方法来强制一个朴素的datetime对象到UTC。我已经通过了replace(tzinfo=…)。我感觉到你的痛苦。