使用pytz进行日期时间和时区转换 - 令人惊叹的行为

35

我正在尝试将时区感知的datetime对象转换为UTC,然后再转回其原始时区。我有以下代码片段:

t = datetime(
    2013, 11, 22, hour=11, minute=0,
    tzinfo=pytz.timezone('Europe/Warsaw')
)

现在在IPython中:

In [18]: t
Out[18]: datetime.datetime(
    2013, 11, 22, 11, 0, tzinfo=<DstTzInfo 'Europe/Warsaw' WMT+1:24:00 STD>
)

现在让我们尝试将时间转换为UTC,然后再转回来。我希望得到的表示形式与以下相同:

In [19]: t.astimezone(pytz.utc).astimezone(pytz.timezone('Europe/Warsaw'))
Out[19]: datetime.datetime(
    2013, 11, 22, 10, 36, tzinfo=<DstTzInfo 'Europe/Warsaw' CET+1:00:00 STD>
)

然而,我们发现Out[18]Out[19]不同。发生了什么?


1
Django将datetimes存储为naive database wise。如果您处理这种情况,请查看此处以将日期转换为所需的时区:https://docs.djangoproject.com/en/dev/topics/i18n/timezones/#usage - Jingo
Django是否存储原始日期时间取决于USE_TZ设置。如果为True,则Django将表单中的日期时间视为处于当前时区,并将其转换为UTC存储在数据库中。 - Anentropic
2
你能进一步说明一下“惊人的行为”是什么吗?我不喜欢在StackExchange上看到标题党。 - Martin Thoma
1个回答

71
文件 http://pytz.sourceforge.net/ 中提到:“遗憾的是,在许多时区中,使用标准日期时间构造函数的 tzinfo 参数无法与 pytz 兼容。” 代码如下:
t = datetime(
    2013, 5, 11, hour=11, minute=0,
    tzinfo=pytz.timezone('Europe/Warsaw')
)

根据此,无法正常工作,相反应该使用localize方法:
t = pytz.timezone('Europe/Warsaw').localize(
        datetime(2013, 5, 11, hour=11, minute=0))

26
Python datetime模块假定时区对象具有恒定的UTC偏移量。而pytz时区对象具有不同的UTC偏移量(因为夏令时以及历史时区变更)。当使用pytz的localize()方法时,它可以为特定日期选择正确的偏移量。但是,如果使用datetime的replace(tzinfo==)方法,则会得到数据库中该时区的最早UTC偏移量。 - Marius Gedminas

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接