datetime.replace 从根本上坏了吗?



将时区简单日期时间转换为特定时区会得到完全不正确的结果。

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时区,则应使用带有天真datetimepytz.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

相关内容

  • 没有找到相关文章

最新更新