Timezones in Python

2 min read
pythontimezonesnaive

After struggling for a while to determine how to convert from one timezone to another in Python I thought I'd write a quick little guide on it. Even if the only person it helps is me a few months from now I'll consider it a success!

It all started when I received the error ValueError: Not naive datetime (tzinfo is already set). A little bit later I received the error ValueError: astimezone() cannot be applied to a naive datetime. It was about this time that I realized I needed to learn what was actually going on.

The naive datetime

Datetimes in Python can either be Naive or Aware. A naive datetime is a datetime that doesn't know its own timezone. It could be in UTC, it could be in US/Eastern, but it doesn't know. All it knows is which date and time that it has.

import datetime
date = datetime.datetime(2015, 11, 11, 11, 0)
date.tzinfo # None
date.strftime("%a %b %d %H:%M:%S %Y") # Wed Nov 11 13:00:00 2015

At this point we don't know if it is 11AM EST, UTC... it is up for the programmer to keep track of which timezone they are working in.

Making it aware

To make our naive datetime aware of its timezone, we can use the pytz library. Let's make our date be in UTC time. We'll do this by using the localize method of a timezone.

import pytz
utc = pytz.timezone('UTC')
aware_date = utc.localize(date)
aware_date.tzinfo # <UTC>
aware_date.strftime("%a %b %d %H:%M:%S %Y") # Wed Nov 11 13:00:00 2015

Converting to another timezone

Now let's take our aware date (in UTC) and convert it to a date in the US/Eastern timezone. To do this we can again use pytz along with a method of datetime called astimezone.

eastern = pytz.timezone('US/Eastern')
eastern_date = aware_date.astimezone(eastern)
eastern_date.tzinfo # <DstTzInfo 'US/Eastern' EST-1 day, 19:00:00 STD>
eastern_date.strftime("%a %b %d %H:%M:%S %Y") # Wed Nov 11 08:00:00 2015

Wrapping things up

We started with a naive date which was unaware of which timezone it was in. We made it aware by localizing it to the UTC timezone, and then we took that aware date and converted it into the US/Eastern timezone.