将时区简单日期时间转换为特定时区会得到完全不正确的结果。
import dateutil as du
import pytz
du.parser.parse('2017-05-31T15:00:00').replace(tzinfo=pytz.timezone('Europe/London')).isoformat()
返回一分钟而不是一小时与 UTC 的偏移量
'2017-05-31T15:00:00-00:01'
我以前见过一些日期时间的特殊性,但这个令人叹为观止。
这里的主要问题是您使用的是pytz
时区。pytz
区域不遵循tzinfo
接口,不能简单地附加到datetime
对象(通过构造函数或通过replace
(。如果要使用pytz
时区,则应使用带有天真datetime
的pytz.timezone.localize
。如果datetime
已识别时区,则可以使用datetime.astimezone
在区域之间转换它。
from dateutil import parser
import pytz
LON = pytz.timezone('Europe/London')
dt = parser.parse('2017-05-31T15:00:00')
dt = LON.localize(dt)
print(dt) # 2017-05-31 15:00:00+01:00
这是因为pytz
的接口使用localize
将静态时区附加到datetime
。出于同样的原因,如果你对现在本地化的datetime
对象进行算术运算,它可能会给出类似的错误结果,你必须使用pytz.timezone.normalize
来修复它。这样做的原因是,从历史上看,使用Pythonictzinfo
接口处理不明确的日期时间是不可能的,在Python 3.6中,PEP 495改变了,使得pytz
的解决方法变得不那么必要。
如果你想使用replace
或构造函数将tzinfo
传递给datetime
,或者你更喜欢使用 pythonic 接口,dateutil
的时区套件实现了符合 PEP 495 的tzinfo
接口。使用dateutil
区域的等效项为:
from dateutil import parser
from dateutil import tz
LON = tz.gettz('Europe/London')
dt = parser.parse('2017-05-31T15:00:00').replace(tzinfo=LON)
print(dt) # 2017-05-31 15:00:00+01:00
我经常在tzinfo
对象中使用replace()
时运气不好。 但是,我发现这种结构是可靠的:
法典:
def naive_to_aware(ts, tz):
return tz.localize(ts)
从评论更新:
来自(pytz DOCS(
不幸的是,在许多时区使用标准日期时间构造函数的 tzinfo 参数"不适用于"pytz。
对于没有夏令时转换的时区是安全的,例如 UTC
因此,这不仅是运气不好,对于时区具有 DST 的 pytz 对象来说,这是有问题的。
测试代码:
import dateutil as du
import pytz
print(naive_to_aware(du.parser.parse('2017-05-31T15:00:00'),
pytz.timezone('Europe/London')).isoformat())
结果:
2017-05-31T15:00:00+01:00