将时区天真日期时间转换为特定时区会产生完全错误的结果。
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'
我之前看过一些日期时间的特点,但这一点令人叹为观止。
答案 0 :(得分:1)
我经常使用replace()
tzinfo
对象运气不好。然而,我发现这个结构是可靠的:
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
答案 1 :(得分:1)
这里的主要问题是您使用的是pytz
时区。 pytz
区域不遵循tzinfo
界面,不能简单地附加到datetime
对象(通过构造函数或通过replace
)。如果您想使用pytz
个时区,则应使用pytz.timezone.localize
与天真datetime
。如果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
来修复它。这样做的原因是,从历史上看,使用Pythonic tzinfo
接口处理模糊日期时间是不可能的,该接口在Python 3.6中使用PEP 495更改,使得pytz
'解决方法不太必要。
如果您想使用tzinfo
或构造函数将datetime
传递给replace
,或者您希望使用pythonic界面,dateutil
的时间zone suite实现符合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