dateutil and pytz give different results
datetime, python, python-dateutil, pytz, timezone
Solution
Edit: The discrepancy discussed below no longer exists when using
>>> dateutil.__version__
'1.5'
>>> pytz.__version__
'2012c'
The pytz module warns,
this library differs from the documented Python API for tzinfo implementations; if you want to create local wallclock times you need to use the localize() method
and further on
This library only supports two ways of building a localized time. The first is to use the localize() method provided by the pytz library.
In [61]: u4 = pytz.timezone('America/Chicago')
In [62]: print(u4.localize(datetime.datetime(2010, 5, 2, 11, 10)))
2010-05-02 11:10:00-05:00
The other way is to use the `astimezone` method, which is used to convert a timezone-aware datetime into another timezone-aware datetime.
And to be completely explicit, it warns against constructing a timezone-aware datetime using the `tzinfo` argument:
Unfortunately using the tzinfo argument of the standard datetime constructors ‘’does not work’’ with pytz for many timezones.
Let's test the hypothesis that
datetime.datetime(year, month, day, hour, minute, tzinfo = dateutil_tz)
equals
pytz_tz.localize(datetime.datetime(year, month, day, hour, minute))
with this code:
import dateutil.tz
import datetime
import pytz
now = datetime.datetime.now()
for name in pytz.all_timezones:
dateutil_tz = dateutil.tz.gettz(name)
pytz_tz = pytz.timezone(name)
dateutil_date = datetime.datetime(
now.year, now.month, now.day, now.hour, now.minute, tzinfo = dateutil_tz)
pytz_date = pytz_tz.localize(datetime.datetime(
now.year, now.month, now.day, now.hour, now.minute))
try:
assert dateutil_date.isoformat() == pytz_date.isoformat()
except AssertionError:
print(name)
print(dateutil_date.isoformat())
print(pytz_date.isoformat())
The code yields:
America/Argentina/San_Luis
2012-12-18T22:32:00-04:00 <-- dateutil datetime
2012-12-18T22:32:00-03:00 <-- pytz's datetime
So my hypothesis was wrong: dateutil and pytz return different results.
So which one is correct? I'm not really sure, but according to this website, currently,
America/Argentina/San_Luis time zone offset is:
UTC / GMT -03:00 hours
so it appears pytz is correct.
Problem
I have an issue comparing outputs with `dateutil` and `pytz`. I'm creating a aware datetime object (UTC) and then converting to a given time zone, but I get different answers. I suspect that dateutil sometimes gives wrong results because it has problems taking into account daylight saving time (at least, I read a comment about it) but I can't find confirmation or a fix to that issue. This is the code: ``` import dateutil u = dateutil.tz.tzutc() date1 = datetime.datetime(2010, 5, 2, 11, 10, tzinfo=u) # 2010-05-02 11:10:00+00:00 u2 = dateutil.tz.gettz('America/Chicago') date2 = datetime.datetime(2010, 5, 2, 11, 10, tzinfo=u2) # 2010-05-02 11:10:00-05:00 import pytz u = pytz.timezone('UTC') date1 = datetime.datetime(2010, 5, 2, 11, 10, tzinfo=u) # 2010-05-02 11:10:00+00:00 u2 = pytz.timezone('America/Chicago') date2 = datetime.datetime(2010, 5, 2, 11, 10, tzinfo=u2) # 2010-05-02 11:10:00-06:00 ``` So, what could be the problem here? UPDATE: I just tried this: ``` print u2.normalize(date1.astimezone(u2)) # 2010-05-02 06:10:00-05:00 ``` So pytz needs `normalize` to consider DST? UPDATE 2: It seemed as if pytz and dateutil don't give the answer for America/Argentina/San_Luis but this works: ``` import pytz, dateutil, datetime now = datetime.datetime.now() for zone in pytz.all_timezones: utc_dateutil = dateutil.tz.tzutc() utcdate_dateutil = datetime.datetime(now.year, now.month, now.day, now.hour, now.minute, tzinfo=utc_dateutil) zone_dateutil = dateutil.tz.gettz(zone) newzone_dateutil = utcdate_dateutil.astimezone(zone_dateutil) utc_pytz = pytz.timezone('UTC') utcdate_pytz = datetime.datetime(now.year, now.month, now.day, now.hour, now.minute, tzinfo=utc_pytz) zone_pytz = pytz.timezone(zone) newzone_pytz = utcdate_pytz.astimezone(zone_pytz) assert newzone_dateutil == newzone_pytz ``` Am I missing something?