I would like to calculate how many hours there are in a date interval: for example "2014.03.29-30" should give 47, because of the daylight savings.
My method is making two datetime objects, in the example the following:
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)
However, it gives "2 days, 0:00:00", which is not correct. How could I make a timedelta object which takes timezones and dst into account? Also, if there's a simpler solution for the whole problem, I'm open to it.
Thank you!
Before 1901-12-13 20:45:52 UTC, the 'Europe/Budapest'
timezone was LMT+1:16:00 STD.
Currently, as of 2016-05-05, the 'Europe/Budapest'
timezone is CET+2:00:00 DST.
If you use pytz's localize
method, then pytz will choose the timezone (utcoffset and dstoffset) for 'Europe/Budapest'
which is appropriate for the given naive datetime:
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>)
In contrast, if you supply tzinfo=tzone
directly to datetime.datetime
, as in:
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>)
then the datetime.datetime
incorrectly chooses the very first timezone associated with 'Europe/Budapest'
regardless of whether or not that was the timezone in effect on 2014-3-29.
Therefore, when using pytz, always use tzone.localize
to make naive datetimes timezone-aware:
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
unless tzone
is pytz.utc
(or a timezone which is alway the same throughout its history.)
Where did the date 1901-12-13 20:45:52 UTC
come from?
You can peek at a pytz timezone's utc transition times (and associated transition info) using its tzone._utc_transition_times
and tzone._transition_info
private attributes:
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')]
This shows that from the date 1-1-1 UTC
to 1901-12-13 20:45:52 UTC
the timezone abbreviation was LMT
and the utcoffset was 4560 seconds, which equals 1 hour and 16 minutes:
In [47]: print(DT.timedelta(0, 4560))
1:16:00
Hence the first timezone associated with 'Europe/Budapest'
is LMT+1:16:00 STD
.