unexpected results converting timezones in python unexpected results converting timezones in python python python

unexpected results converting timezones in python


What I got is just a workaround, the simple rule is Never create datetime with timezone info by using datetime().

This sample would give you a hint for this. As you see, you could avoid the unexpected difference, once and only you make "naive" datetime (it is, datetime without timezone info) and then localize it (it is not applied when you create datetime on UTC though) :

import pytzfrom datetime import datetime# make Jan 1 on PDT -> UTCpdt = pytz.timezone("America/Los_Angeles")pdtnow1 = datetime(2014,1,1, tzinfo=pdt)pdtnow2 = pdt.localize(datetime(2014,1,1))pytz.utc.normalize(pdtnow1)# > datetime.datetime(2014, 1, 1, 7, 53, tzinfo=<UTC>)pytz.utc.normalize(pdtnow2)# > datetime.datetime(2014, 1, 1, 8, 0, tzinfo=<UTC>)# make Jan 1 on UTC -> PDTutcnow1 = datetime(2014,1,1, tzinfo=pytz.utc)utcnow2 = pytz.utc.localize(datetime(2014,1,1))pdt.normalize(utcnow1)# > datetime.datetime(2013, 12, 31, 16, 0, # > tzinfo=<DstTzInfo 'America/Los_Angeles' PST-1 day, 16:00:00 STD>)pdt.normalize(utcnow2)# > datetime.datetime(2013, 12, 31, 16, 0, # > tzinfo=<DstTzInfo 'America/Los_Angeles' PST-1 day, 16:00:00 STD>)


From the partial documentation:http://pytz.sourceforge.net/#localized-times-and-date-arithmetic

Unfortunately using the tzinfo argument of the standard datetime constructors ‘’does not work’’ with pytz for many timezones. [...] It is safe for timezones without daylight saving transitions though, such as UTC. [...] The preferred way of dealing with times is to always work in UTC, converting to localtime only when generating output to be read by humans.


Unfortunately, creating timezone aware dates using this method doesn't work.

If you are using Django, they have a utility function, make_aware, that does this correctly.

from django.utils.timezone import make_awarefrom pytz import timezoneunaware_datetime = datetime(2007, 12, 5)local_datetime = make_aware(datetime(2007, 12, 5))specific_datetime = make_aware(datetime(2007, 12, 5), timezone("Australia/Melbourne"))

If you're not using Django, then the source code for the make_aware function may give you inspiration.