奇怪的.astimezone行为

ibz*_*ibz 9 python pytz

我正在做一些时区转换,我得到了非常奇怪的结果.基本上只在整个小时不同的时区之间进行转换,我仍然得到非完整的结果.例如:

from datetime import datetime
from pytz import timezone

datetime(2013, 12, 27, 20, 0, 0, tzinfo=timezone('Europe/Bucharest'))\
    .astimezone(timezone('Europe/Berlin')).replace(tzinfo=None)
Run Code Online (Sandbox Code Playgroud)

给我

datetime.datetime(2013, 12, 27, 19, 16)
Run Code Online (Sandbox Code Playgroud)

(布加勒斯特和柏林之间的时差是1小时,所以我应该得到19:00 - 而不是19:16)

我可能错过了一些非常明显的东西,但我无法弄清楚.我究竟做错了什么?

Nic*_*tot 10

pytz文档指定:

不幸的是,对于许多时区,使用标准日期时间构造函数的'tzinfo参数''与pytz不兼容.

实际上,这不是预期的结果,时区错了:

>>> datetime(2013, 12, 27, 20, 0, 0, tzinfo=timezone('Europe/Bucharest'))
datetime.datetime(2013, 12, 27, 20, 0,
    tzinfo=<DstTzInfo 'Europe/Bucharest' BMT+1:44:00 STD>)
Run Code Online (Sandbox Code Playgroud)

这个解释了pytz构造函数给定时timezone('Europe/Bucharest')区不检查何时应该考虑时区偏移,并且这些事情往往会随着时间而改变.pytz只使用早期已知的定义,这通常是错误的:

>>> timezone('Europe/Bucharest')
<DstTzInfo 'Europe/Bucharest' BMT+1:44:00 STD>
Run Code Online (Sandbox Code Playgroud)

看起来这个时区一直使用到1931年.

使用UTC时间并使用它们进行转换时astimezone(仅出于显示目的),没有此类问题:

>>> datetime(2013, 12, 27, 20, 0, 0, tzinfo=pytz.utc)\
    .astimezone(timezone('Europe/Bucharest')) 
datetime.datetime(2013, 12, 27, 22, 0,
    tzinfo=<DstTzInfo 'Europe/Bucharest' EET+2:00:00 STD>)
Run Code Online (Sandbox Code Playgroud)

然后你得到预期的结果:

>>> datetime(2013, 12, 27, 20, 0, 0, tzinfo=pytz.utc)\
    .astimezone(timezone('Europe/Bucharest'))\
    .astimezone(timezone('Europe/Berlin'))\
    .replace(tzinfo=None)
datetime.datetime(2013, 12, 27, 21, 0)
Run Code Online (Sandbox Code Playgroud)

  • @ibz:正确的调用是`pytz.timezone('Europe/Bucharest').localize(datetime(2013,12,27,20),is_dst = None)`如[pytz docs](http)的开头所说的那样://pytz.sourceforge.net/#introduction).如果输入日期在布加勒斯特时区,则使用`pytz.utc`是错误的. (3认同)

Chr*_*ris 8

我今天遇到了同样的问题,并最终使用当前接受的答案的评论中的答案@jfs 解决了它。为了帮助其他人将来发现这一点,这里有一个简单的示例,说明什么有效,什么无效:

from datetime import datetime
import pytz

naive = datetime.now()
la_tz = pytz.timezone("America/Los_Angeles")

# this doesn't work
with_tz = naive.replace(tzinfo=la_tz)
converted_to_utc = with_tz.astimezone(pytz.utc)
print(converted_to_utc)

# this does work
with_tz = la_tz.localize(naive)
converted_to_utc = with_tz.astimezone(pytz.utc)
print(converted_to_utc)
Run Code Online (Sandbox Code Playgroud)

  • 谢谢@Chris,这有效。我的情况是从 utc 到其他 tz。 (2认同)