在python中转换时区时出现意外结果

在python中转换时区时出现意外结果,python,pytz,Python,Pytz,我试图理解为什么在将时区转换为UTC时会得到这些结果: In [74]: d1 = datetime(2007, 12, 5, 6, 30,tzinfo=pytz.timezone('US/Pacific')) In [75]: d1 Out[75]: datetime.datetime(2007, 12, 5, 6, 30, tzinfo=<DstTzInfo 'US/Pacific' LMT-1 day, **16:07:00 STD**>) In [76]: d1.astime

我试图理解为什么在将时区转换为UTC时会得到这些结果:

In [74]: d1 = datetime(2007, 12, 5, 6, 30,tzinfo=pytz.timezone('US/Pacific'))
In [75]: d1
Out[75]: datetime.datetime(2007, 12, 5, 6, 30, tzinfo=<DstTzInfo 'US/Pacific' LMT-1 day, **16:07:00 STD**>)
In [76]: d1.astimezone(pytz.utc)
Out[76]: datetime.datetime(2007, 12, 5, 14, 23, tzinfo=<UTC>)
In[74]:d1=datetime(2007,12,5,6,30,tzinfo=pytz.timezone('US/Pacific'))
In[75]:d1
Out[75]:datetime.datetime(2007,12,5,6,30,tzinfo=)
In[76]:d1.astimezone(pytz.utc)
Out[76]:datetime.datetime(2007,12,5,14,23,tzinfo=)
为什么早上6:30变成了下午2:23

另一方面,如果我使用以下方法,我会得到预期的结果:

In [90]: d2 = datetime(2007, 12, 5, 6, 30)
In [91]: uspac = pytz.timezone('US/Pacific')
In [92]: d2_aware = uspac.localize(d2)
In [94]: d2_aware.astimezone(pytz.utc)
Out[94]: datetime.datetime(2007, 12, 5, 14, 30, tzinfo=<UTC>)
[90]中的
:d2=datetime(2007,12,5,6,30)
在[91]中:uspac=pytz.timezone('美国/太平洋')
在[92]中:d2_aware=uspac.localize(d2)
在[94]中:d2_-aware.astimezone(pytz.utc)
Out[94]:datetime.datetime(2007,12,5,14,30,tzinfo=)

之前打印
d2\u aware
。astimezone
,您会看到
PST-1
(太平洋标准时间),但在第一个示例中,您有
LMT-1
(本地平均时间)-可能会有7分钟的差异


但是我不知道为什么pytz使用不同的时区。

部分文档:

不幸的是,对于许多时区,使用标准datetime构造函数的tzinfo参数“不适用于”pytz。[…]但对于没有夏令时转换的时区(如UTC)是安全的。[…]处理时间的首选方法是始终使用UTC,仅在生成供人读取的输出时才转换为localtime


我得到的只是一个解决办法,简单的规则是永远不要使用datetime()使用时区信息创建datetime

此示例将为您提供这方面的提示。如您所见,您可以避免意外的差异,只需将datetime设置为“naive”(即没有时区信息的datetime),然后将其本地化(但在UTC上创建datetime时不应用):

导入pytz 从日期时间导入日期时间 #在PDT->UTC上创建1月1日 pdt=pytz.时区(“美国/洛杉矶”) pdtnow1=日期时间(2014,1,1,tzinfo=pdt) pdtnow2=pdt.本地化(日期时间(2014,1,1)) pytz.utc.normalize(pdtnow1) #>datetime.datetime(2014,1,1,7,53,tzinfo=) pytz.utc.normalize(pdtnow2) #>datetime.datetime(2014,1,1,8,0,tzinfo=) #在UTC->PDT上创建1月1日 utcnow1=日期时间(2014,1,1,tzinfo=pytz.utc) utcnow2=pytz.utc.localize(日期时间(2014,1,1)) pdt规范化(utcnow1) #>datetime.datetime(2013、12、31、16、0、, #>tzinfo=) pdt.标准化(utcnow2) #>datetime.datetime(2013、12、31、16、0、, #>tzinfo=)
我正在重新考虑一些关于日期和时间的问题,看看是否有一些较新的库在这种情况下更有用(或者没有)。是一个存储有日期和时间的时区,在这种情况下特别有价值

>>> import pendulum
>>> d1 = pendulum.datetime(2007,12,5,6,30, tzinfo='US/Pacific')
>>> d1
<Pendulum [2007-12-05T06:30:00-08:00]>
>>> d1.timezone
<Timezone [US/Pacific]>
>>> d1.astimezone(tz='UTC')
<Pendulum [2007-12-05T14:30:00+00:00]>
导入钟摆 >>>d1=钟摆日期时间(2007,12,5,6,30,tzinfo='US/Pacific') >>>d1 >>>d1.时区 >>>d1.散光区(tz='UTC')
还有很多其他的甜蜜功能。

不幸的是,使用此方法创建时区感知日期不起作用

如果您使用的是Django,那么它们有一个实用函数,可以正确地执行此操作

from django.utils.timezone import make_aware
from pytz import timezone

unaware_datetime = datetime(2007, 12, 5)
local_datetime = make_aware(datetime(2007, 12, 5))
specific_datetime = make_aware(datetime(2007, 12, 5), timezone("Australia/Melbourne"))

如果您没有使用Django,那么make_-aware函数的功能可能会给您带来灵感。

当我持续几分钟查看结果时,我以为自己疯了。“非常感谢你给我举的这个例子。”我很乐意为你效劳!正是网络搜索7:53的偏移量帮助我找到了这个问题。我想,现在美国太平洋时间的夏令时已经开始了,七分钟不知何故被加到了偏移量中,而不是一小时?真奇怪!python的这一部分看起来很混乱,因为meIt在两次转换时区方面仍然存在问题。localize(datetime(2014,1,1)\.astimezone(other_timezone)谢谢!我一辈子都搞不懂这一点!不幸的是,“没有夏令时转换的时区是安全的”这句话太乐观了。对于固定偏移量多年来发生变化的时区,它也会失败。幸运的是UTC没有变化。Django的
make_-aware(dt)
只是调用
pytz.timezone(…).localize(dt)
from django.utils.timezone import make_aware
from pytz import timezone

unaware_datetime = datetime(2007, 12, 5)
local_datetime = make_aware(datetime(2007, 12, 5))
specific_datetime = make_aware(datetime(2007, 12, 5), timezone("Australia/Melbourne"))