Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django seems to be displaying datetimes in UTC format

In settings.py I have:

TIME_ZONE = 'Asia/Singapore'
USE_I18N = True
USE_L10N = True
USE_TZ = True

If a user (who is living in Singapore) enters 2013-10-07 01:00 A.M. in a form on my site, the value stored in my (PostgreSQL) database is 2013-10-07 01:00:00+08. When I pull up this information during a python manage.py shell session, I get 2013-10-06 17:00:00+00:00. The same happens when I try to render this information in a template.

What I think is happening: Django recognizes that the user is entering 1:00 A.M. on October 10th, Singapore time, and stores this in the database as 2013-10-07 01:00:00+08. However, when Django retrieves this info from the database, it formats it to UTC time, thereby giving 2013-10-06 17:00:00+00:00.

Do I have that right? And if so, what can I do to make Django display times using the same timezone information that is stored in the database (or at least using my TIME_ZONE setting)? In other words, how can I make it so that the user sees the datetime in the exact same form as she entered it?

like image 718
GChorn Avatar asked Oct 02 '13 09:10

GChorn


People also ask

How do I change the default timezone in Django?

The solution to this problem is to use UTC in the code and use local time only when interacting with end users. Time zone support is disabled by default. To enable it, set USE_TZ = True in your settings file. In Django 5.0, time zone support will be enabled by default.

Is datetime UTC by default?

If Server sends Date in UTC format it is automatically default to local time. That is DateTime.

What is the format of datetime in Django?

Python django format date dd/mm/yyyy.

Is datetime stored in UTC?

Rule #1 - STORE DATETIMES IN UTC IN YOUR DATABASE, AND BACK END CODE. It is important that there is consistency across all your date-related data. When storing dates in the database, they should always be in UTC.


2 Answers

I've figured out what's going on. Based on what I had read in the docs here, I was assuming that with USE_TZ=True, Django would output datetimes in the current time zone (which defaults to the TIME_ZONE setting) everywhere--views, the shell, etc.

However, it turns out that Django only makes the conversion in templates, and even then only in the most direct, basic invocation of a datetime object.

Specifically, if you have an object with a DateTimeField and you render its datetime attribute in a template using {{ object.datetime }}, you will get a datetime converted to the current time zone. Yay. However, this functionality won't work for anything else, even within templates, such as {{ object.datetime.hour }} (which will display the hour in UTC). So it's basically just an invisible template tag. Not as magical as I'd hoped!

It looks like I'll need to convert all datetimes to the current time zone in my views before passing them to my templates. I find this kind of weird and counterintuitive considering that my database already has all of the datetimes stored in the time zone I want them displayed in. Wouldn't it make more sense to have to explicitly tell Django you want database values expressed in UTC, than to have Django perform the work automatically and then make you change them back in your views?

EDIT: This answer on SO made the solution to my specific situation considerably easier:

from django.utils.timezone import localtime

result = localtime(some_time_object)

EDIT: It turns out that only PostgreSQL stores time zone information, and that information is separate from the raw datetime values it stores, which are in UTC. So I guess it makes sense for Django to render everything in UTC by default, since other database backends don't even store time zone info.

like image 103
GChorn Avatar answered Oct 15 '22 14:10

GChorn


Have you looked at the localtime template tag

update: However that does refer to setting USE_TZ to True as you have

like image 30
rockingskier Avatar answered Oct 15 '22 13:10

rockingskier