关于pytz:python中转换时区的意外结果

unexpected results converting timezones in python

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

1
2
3
4
5
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>)

为什么早上6:30变成下午2:23?

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

1
2
3
4
5
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>)

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

此示例将为此提供提示。如您所见,您可以避免意外的差异,只需将"naive"日期时间(即,不带时区信息的日期时间)设置为一次,然后将其本地化(但在UTC上创建日期时间时不应用它):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import pytz
from datetime import datetime

# make Jan 1 on PDT -> UTC
pdt = pytz.timezone("America/Los_Angeles")
pdtnow1 = datetime(2014,1,1, tzinfo=pdt)
pdtnow2 = pdt.localize(datetime(2014,1,1))
pytz.utc.normalize(pdtnow1)
# > datetime.datetime(2014, 1, 1, 7, 53, tzinfo=<UTC>)
pytz.utc.normalize(pdtnow2)
# > datetime.datetime(2014, 1, 1, 8, 0, tzinfo=<UTC>)

# make Jan 1 on UTC -> PDT
utcnow1 = datetime(2014,1,1, tzinfo=pytz.utc)
utcnow2 = pytz.utc.localize(datetime(2014,1,1))
pdt.normalize(utcnow1)
# > datetime.datetime(2013, 12, 31, 16, 0,
# > tzinfo=<DstTzInfo 'America/Los_Angeles' PST-1 day, 16:00:00 STD>)
pdt.normalize(utcnow2)
# > datetime.datetime(2013, 12, 31, 16, 0,
# > tzinfo=<DstTzInfo 'America/Los_Angeles' PST-1 day, 16:00:00 STD>)


从部分文件:http://pytz.sourceforge.net/本地化时间和日期算法

Unfortunately using the tzinfo argument of the standard datetime constructors ‘’does not work’’ with pytz for many timezones. [...] It is safe for timezones without daylight saving transitions though, such as UTC. [...] The preferred way of dealing with times is to always work in UTC, converting to localtime only when generating output to be read by humans.


我在复习一些关于日期和时间的问题,看看在这种情况下(或不这样)一些新的库是否更有帮助。钟摆是一种存储带有日期和时间的时区的方法,它在这种情况下特别有价值。

1
2
3
4
5
6
7
8
>>> 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]>

还有很多其他可爱的特征。


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

如果您使用的是django,它们有一个实用功能,请注意,这是正确的。

1
2
3
4
5
6
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"))

.astimezone之前打印d2_aware,您会看到PST-1(太平洋标准时间),但在第一个例子中,您使用LMT-1(本地平均时间),可能会产生7分钟的差异。

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