How timezones work in Django

There was a joke floating around the internet that if Elon Musk figures out how to get to mars, software developers won't be happy because there would be more time zones to support.

If you’re building an application that is going to be used by folks all around the world, they will be interacting with the application in their own local time zone.

This means that whatever records they see on their browsers or phones should have timestamps in their local timezone. 

But we cannot store these timestamps on the backend in their local time zone because that would conflict with records of other users on different time zones. 

I suppose timestamps can be stored along with the time zone information, but this makes it very hard to build software. 

For instance what if you want to query all users who installed your app during a certain period of time? Getting this data will be next to impossible if all records are stored in their respective time zones.

So how do we keep every user in sync? And more importantly how does Django handle this?

Coordinated Universal Time (UTC)

Before we get into how to handle this problem in Django, let's talk about how the world handles it. 

A time zone is nothing but a section of the earth where everyone observes the same time. But even a particular time zone may not follow the same time throughout the year due to something called daylight savings time which is too big of a topic in itself to get into right now.

Because of all these complexities, the world agreed to use a common standard for time that remains the same no matter where you are or what time of the year it is. This is known as the coordinated universal time or UTC.

UTC is maintained using an atomic clock that is very precise. All time zones are a positive or negative offset of UTC.

For instance I live in India which is 5 hours and 30 minutes ahead of UTC, so at the time of writing this post, the time was 10:32:10 PM UTC+5:30.

This can also be written as 10:32:10 PM GMT+5:30. In terms of time, there is no difference between GMT and UTC, however GMT is a time zone whereas UTC is a standard against which time is measured.

Timezone support in Django

At this point, it is quite obvious that our application should always deal with UTC time regardless of where the user is from. 

In order to make sure this happens, you just need to configure a couple of things in the of your Django application.

This will ensure that using a anywhere in your application always creates time in UTC. If USE_TZ is set to False, Django will assume that your application does not care about time zones and will create timestamps in the local time zone.

Local timezone here would be wherever you are hosting the Django application, so if you are running it locally on your computer it will use your computer's time and if you are running it on the cloud on a United States server, it will use that time.

I am sure you can see how this can result in chaos, so I would highly recommend using these two settings.

Displaying local time in browsers

To do this, simply convert your UTC time to this format: %Y-%m-%dT%H:%M:%SZ. 

For more clarity on what this format means, consider the time at which I was writing this blog post which was 10:32 PM in Indian Standard Time on the 27th of Feb 2021. 

This will be translated to 2020-02-27T05:02:00Z. This is because we have modified it from IST to UTC and used the format shown above.

The javascript that is rendering the timestamp on the browser will understand from this that the time is set in UTC and needs to be converted to whatever time zone the browser is running on before displaying it to the user.

You can verify this by pulling up the developer console on your chrome browser and trying this out.

Date-Time in Javascript

As you can see, even though I invoked the Date class using the time format in UTC, it automatically converted it to IST.

But what does this time format mean exactly? The “T” is meant to separate date and time while the “Z” is meant to indicate that the timestamp is in UTC.

Easy peasy right? Indeed it is!

Using the DateTimeField in your Django models.

It is generally a good practice to have fields in your models to determine when an object was created and when it was last modified.

Apart from these two fields you might need other fields that store timestamps based on your use case. 

This can be achieved using the DateTimeField offered by Django models. As shown in the example below, one can have a created_at field and a last_updated_on field that get updated automatically when an object of this model is saved.

auto_now_add will ensure that the value of this field is automatically set to when the record is created for the first time.

auto_now will ensure that the value of this field is automatically updated to every time this object is saved.

If you followed the previous time zone settings in your, these fields will ensure that they are always being set in UTC.

Closing notes

To sum it up, make sure that time is always stored in UTC and things should be fine. 

If you want to handle issues pertaining to daylight savings time, I highly recommend using the pytz library which is built to handle these kinds of edge cases.

If you want to know more about how time zones work, this article was very informative and also describes how pytz is useful.

I hope you have a good “time”. Sorry, I could not resist :)