Proper Time Zone Support
Previously, I gave you a quick overview of the course. In this lesson, I’ll be talking about the new
zoneinfo library. By default, timestamps created with the
datetime module have no time zone information.
You can add a time zone to a date using the
tz attribute in the date/time creation methods. Timestamps without time zone information are called naive.
datetime.now() without any parameters returns a naive datetime. By passing in a
tz parameter, you can set a time zone to be associated with the timestamp.
In this case here, I’ve passed in
utc. Previous to Python 3.9, the only time zone that came out of the box was UTC. You had to subclass it or use a third-party library in order to use time zones besides UTC.
01:06 You can specify times zones by name, and there are hundreds of them—including historic values—available. The library also handles the name changes that happen if your time zone switches into Daylight Savings Time.
now() returns the current datetime. This is a naive datetime; it does not include time zone information. I can use the
timezone module and specify a time zone of
utc, and now I have a datetime including time zone information.
and I get the same datetime stamp, but in the Oslo time zone. It’s converted it for me.
zoneinfo has an
available_timezones() function to list everything that’s in the database. There’s a lot there, so I’m not going to show it all to you.
I’m running this on a Mac, and at the moment there’s
595 items in the database. My colleague who wrote the article that goes with this course—I believe he was using Linux and he got
609, so you’re going to get variation from place to place.
03:16 There aren’t 595 times zones on the planet, so why is there so much information in the database? This is because it includes historical information. As countries change, as borders change, and as countries change their mind about what time zone they’re in—the data shifts.
03:41 This is the time zone for Christmas Island. You might be wondering why I said Christmas. Well, the name of the zone there is actually the Kiribati spelling of the word Christmas. Kiribati pronounces it closer to “kirismash”, but I’m not going to embarrass myself by attempting that. Christmas Island is near the International Date Line. At the end of 1994, the residents of Christmas Island decided they wanted to shift what time zone they were in.
Now I’m going to use
.astimezone() to convert that to Christmas Island’s time zone, and you’ll notice that that’s showing as December 30th. To make the next bit clearer, I’m going to use the
timedelta library to create a variable containing the amount of time in an hour.
And this is where the weirdness happens. The original
.astimezone() was 1994, December 30th. One hour later, it’s 1995, January 1st. Because Christmas Island decided to switch from one side of the date line to the other at the end of 1994, they lost December 31st. It just disappeared. One hour, it was 1994, December 30th. An hour later, it was 1995.
06:14 was 14 hours. They swapped which side of the International Date Line they were on, and everything moved forward by 24 hours. In addition to historical corner cases, you can also see more typical changes like those caused by Daylight Savings Time. Once again, here’s Vancouver.
As I mentioned before, the
ZoneInfo class is getting its time zone information from a database on your computer. Depending on your operating system, the values in that database may be different or could be missing altogether.
Some computers don’t have this database installed, particularly certain versions of Windows. If you go to use the
ZoneInfo class in this case, you’ll get an exception. To make sure all Python programmers are on an equal footing, the folks at Python have also created a
tzdata database, so if your operating system doesn’t ship with the database, you can use
pip install to get a copy of the database maintained by the Python folks.
ZoneInfo has also been backported to earlier versions of Python. You can get this code using
pip install backports.zoneinfo. If you’re trying to write code that uses this module in Python 3.9 or earlier, you can do a
except block importing
zoneinfo or the
backports version of
zoneinfo to make sure that you always get the library.
08:09 Here are a few things to keep in mind when using time zones. If you’re trying to record a timestamp that is a civil time, it should include a time zone. Civil times are things like meetings, train times, concerts—the kinds of thing you would put inside of your calendar.
08:26 These kinds of events tend to be related to a location. Keeping the appropriate time zone allows you to store that information with the timestamp. This is particularly useful if your user is traveling.
08:38 If they happen to be in another time zone, they need to know what the appointment was in the time zone they were in. If you aren’t storing the time zone information, things get muddy quickly. Timestamps, on the other hand, should be naive and based on UTC.
08:54 The typical use of timestamps is inside of server logs. You don’t want to be dealing with the changes in Daylight Savings Time, or time zone changes of a server, or where the server is located when you’re trying to timestamp an event.
09:18 It is possible for an event at 1:30 in the morning to be after an event at 2:00 in the morning in a time zone that uses Daylight Savings Time on the day that it shifts. Because you don’t want to be dealing with this inside of your server logs, stick with a UTC-based timestamp.
Become a Member to join the conversation.