我想计算一个日期间隔中有多少小时:例如“2014.03.29-30”应该给出47,因为夏令时。
我的方法是制作两个日期时间对象,例如以下内容:
datetime.datetime(2014, 3, 29, 0, 0, tzinfo=<DstTzInfo 'Europe/Budapest' LMT+1:16:00 STD>)
datetime.datetime(2014, 3, 30, 23, 59, tzinfo=<DstTzInfo 'Europe/Budapest' LMT+1:16:00 STD>)
return (date2-date1) + timedelta(minutes=1)
但是,它提供“2天,0:00:00”,这是不正确的。我怎样才能制作一个timedelta对象,它将时区和dst考虑在内?此外,如果对整个问题有一个更简单的解决方案,我愿意接受它。
谢谢!
答案 0 :(得分:2)
在1901-12-13 20:45:52 UTC之前,'Europe/Budapest'
时区是LMT + 1:16:00 STD。
目前,截至2016-05-05,'Europe/Budapest'
时区为CET + 2:00:00 DST。
如果您使用pytz的localize
method,则pytz将为'Europe/Budapest'
选择适合给定天真日期时间的时区(utcoffset和dstoffset):
import datetime as DT
import pytz
tzone = pytz.timezone('Europe/Budapest')
date1 = tzone.localize(DT.datetime(2014, 3, 29, 0, 0), is_dst=None)
# datetime.datetime(2014, 3, 29, 0, 0, tzinfo=<DstTzInfo 'Europe/Budapest' CET+1:00:00 STD>)
相反,如果您将tzinfo=tzone
直接提供给datetime.datetime
,例如:
wrong_date1 = datetime.datetime(2014, 3, 29, 0, 0, tzinfo=tzone)
# datetime.datetime(2014, 3, 29, 0, 0, tzinfo=<DstTzInfo 'Europe/Budapest' LMT+1:16:00 STD>)
然后datetime.datetime
错误地选择与'Europe/Budapest'
关联的第一个时区,无论这是否是2014-3-29生效的时区
因此,在使用pytz时,请始终使用tzone.localize
使天真的日期时间知道时区:
import datetime as DT
import pytz
tzone = pytz.timezone('Europe/Budapest')
date1 = tzone.localize(DT.datetime(2014, 3, 29, 0, 0), is_dst=None)
date2 = tzone.localize(DT.datetime(2014, 3, 30, 23, 59), is_dst=None)
print(((date2-date1) + DT.timedelta(minutes=1)).total_seconds()/3600.)
# 47.0
Do not use tzinfo=tzone
除非tzone
是pytz.utc
(或者在整个历史过程中始终相同的时区。)
日期1901-12-13 20:45:52 UTC
来自哪里?
您可以使用其tzone._utc_transition_times
和tzone._transition_info
私有属性来查看pytz时区的utc转换时间(以及相关的转换信息):
In [43]: [(utcdate, utcoffset, dstoffset, tzabbrev) for utcdate, (utcoffset, dstoffset, tzabbrev) in zip(tzone._utc_transition_times, tzone._transition_info)][:2]
Out[43]:
[(datetime.datetime(1, 1, 1, 0, 0),
datetime.timedelta(0, 4560),
datetime.timedelta(0),
'LMT'),
(datetime.datetime(1901, 12, 13, 20, 45, 52),
datetime.timedelta(0, 3600),
datetime.timedelta(0),
'CET')]
这表明,从1-1-1 UTC
到1901-12-13 20:45:52 UTC
,时区缩写为LMT
,utcoffset为4560秒,相当于1小时16分钟:
In [47]: print(DT.timedelta(0, 4560))
1:16:00
因此,与'Europe/Budapest'
相关联的第一个时区为LMT+1:16:00 STD
。