0

I'm struggling to figure out how timezone works in Django. On my systems I have all datetimes in UTC+00 even with a UTC+02 TIME_ZONE setting.

timezone.get_default_timezone()                                                                                                                                                                                                                                                                                                                   
<DstTzInfo 'Europe/Rome' RMT+0:50:00 STD>

timezone.get_current_timezone()                                                                                                                                                                                                                                                                                                                   
<DstTzInfo 'Europe/Rome' RMT+0:50:00 STD>

I'm using PostgreSQL as backend database and I'm using the following settings:

TIME_ZONE = 'Europe/Rome'
USE_TZ = True

The documentations about PostgreSQL say:

... if you’re using PostgreSQL, you can switch between USE_TZ = False and USE_TZ = True freely. The database connection’s time zone will be set to TIME_ZONE or UTC respectively, so that Django obtains correct datetimes in all cases. You don’t need to perform any data conversions.

If from shell I try to get the date_joined field of an User, this one is UTC+00 and not converted to UTC+02 (as expected since I'm using TIME_ZONE)

admin.date_joined                                                                                                                                                                                                                                                                                                                                 
datetime.datetime(2017, 7, 12, 15, 22, 58, tzinfo=<UTC>)

str(admin.date_joined)                                                                                                                                                                                                                                                                                                                            
'2017-07-12 15:22:58+00:00'

The serialized object (DRF) contain the same wrong datetime of course (in UTC+00)

"date_joined": "2017-07-12T15:22:58Z",

Django also offer the possibility to set the favorite TIME_ZONE to end user 's with activate() method, but this is a different thing. By default when I retrieve data from the database all datetimes should be converted to the relative TIME_ZONE settings right?

What I'm missing? where I get wrong?

Kevin Christopher Henry
  • 46,175
  • 7
  • 116
  • 102
realnot
  • 721
  • 1
  • 11
  • 31

1 Answers1

2

It's important to understand that datetimes are converted to the current time zone only when "rendering". That is, when using templates, forms, or, in the case of Django Rest Framework, serializers.

The timezone of the Python datetime object depends on the database connection, and is usually UTC. One reason for this is that timezones are primarily a display issue, so it doesn't really matter what the timezone of your Python object is. A more important reason is that timezone conversions are potentially lossy (since many timezones have ambiguous times around DST), so you really don't want to do this sort of conversion until the very last step.

Kevin Christopher Henry
  • 46,175
  • 7
  • 116
  • 102
  • So If I figured out the problem, is correct to have UTC+00 at DB level and each time I need to show the right datetime to end user's I need to convert it manually using for example timezone.localtime(admin.date_joined) In a view, template or serializer – realnot May 24 '19 at 10:10
  • 1
    @realnot: In views (or anywhere you're dealing with Python `datetime` objects) they will be in UTC. In templates you should see the correct timezone, as described [here](https://docs.djangoproject.com/en/dev/topics/i18n/timezones/#time-zone-aware-output-in-templates). I don't use DRF, but [the documentation](https://www.django-rest-framework.org/api-guide/fields/#datetimefield) implies that you should see it in the correct timezone. It's *rare* that you would need to convert it with `localtime`, for most projects that will never be necessary. – Kevin Christopher Henry May 24 '19 at 10:16
  • So I have to figure out why DRF doesn't perform the conversation since I'm using `USE_TZ = True` with with `TIME_ZONE = 'Europe/Rome'` configured properly! – realnot May 24 '19 at 10:23
  • @realnot: Agreed, that is the one unexpected result in your question. – Kevin Christopher Henry May 24 '19 at 10:29