I am doing some timezone conversions, and I get really weird results. Basically converting between timezones that differ only by whole hours, I still get non-whole results. For example:
from datetime import datetime
from pytz import timezone
datetime(2013, 12, 27, 20, 0, 0, tzinfo=timezone('Europe/Bucharest'))\
.astimezone(timezone('Europe/Berlin')).replace(tzinfo=None)
gives me
datetime.datetime(2013, 12, 27, 19, 16)
(time difference between Bucharest and Berlin is 1 hour, so I should get 19:00 - instead I get 19:16)
I'm probably missing something really obvious, but I can't figure it out. What am I doing wrong?
As specified by the pytz documentation:
Unfortunately using the tzinfo argument of the standard datetime constructors ‘’does not work’’ with pytz for many timezones.
Indeed, this is not the expected result, the timezone is wrong:
>>> datetime(2013, 12, 27, 20, 0, 0, tzinfo=timezone('Europe/Bucharest'))
datetime.datetime(2013, 12, 27, 20, 0,
tzinfo=<DstTzInfo 'Europe/Bucharest' BMT+1:44:00 STD>)
This is explained the pytz
constructor given the timezone('Europe/Bucharest')
timezone does not check when the timezone offset should be considered, and these things tend to change over time. pytz
just uses the earlier known definition, which will often be wrong:
>>> timezone('Europe/Bucharest')
<DstTzInfo 'Europe/Bucharest' BMT+1:44:00 STD>
It looks like this timezone was used until 1931.
There is no such issue when working with UTC times and converting those using astimezone
(for display purposes only as recommended):
>>> datetime(2013, 12, 27, 20, 0, 0, tzinfo=pytz.utc)\
.astimezone(timezone('Europe/Bucharest'))
datetime.datetime(2013, 12, 27, 22, 0,
tzinfo=<DstTzInfo 'Europe/Bucharest' EET+2:00:00 STD>)
Then you get the expected result:
>>> datetime(2013, 12, 27, 20, 0, 0, tzinfo=pytz.utc)\
.astimezone(timezone('Europe/Bucharest'))\
.astimezone(timezone('Europe/Berlin'))\
.replace(tzinfo=None)
datetime.datetime(2013, 12, 27, 21, 0)
I came across this same issue today, and eventually solved it using the answer @jfs put in the comment of the currently accepted answer. To help anyone else finding this in the future, here is a quick example of what does and doesn't work:
from datetime import datetime
import pytz
naive = datetime.now()
la_tz = pytz.timezone("America/Los_Angeles")
# this doesn't work
with_tz = naive.replace(tzinfo=la_tz)
converted_to_utc = with_tz.astimezone(pytz.utc)
print(converted_to_utc)
# this does work
with_tz = la_tz.localize(naive)
converted_to_utc = with_tz.astimezone(pytz.utc)
print(converted_to_utc)