Skip to main content

Timezones. New in Django 1.4.

What and Why?

Under Django version 1.4 all dates stored and displayed for a single timezone. The one that is specified in project.settings.TIME_ZONE. Now you gain ability to store dates in UTC and render it with timezone correction.

Problems with localtime bypass is an additional plus. They can happen once a year. For e.g. 31 of November 2012 in Russia. Time from 2:00am to 3:00am in fact goes by twice. It may not be a problem for 99% of users. But it can become a nightmare for billing systems. So it's better to store time in UTC and display with user Time Zone correction. So "02:15am 31 November 2012" will become "2012-10-30T22:15:00+04:00" and "2010-10-30T23:15:00+03:00" that is so handy for programmers ;).

Concepts

datetime objects in Python support timezones with attribute tzinfo. If this attribute is filled out it is called "timezone-aware", otherwise it's "naive" date.
Django uses timezone-aware dates, if you've used new feature in Django 1.4 while update. (settings.USE_TZ=True)
"Default timezone" in Django is the one that is specified in settings.TIME_ZONE. (E.g. 'Europe/Kiev'). While "current timezone" is the one that activated this moment.

Current timezone

You need to know where is user from to show him his date and time. You can ask him directly and store his timezone in session BTW. You can use DB's like "maxmind", guessing his timezone by IP or even use JavaScript: Date.getTimezoneOffset(). One or another way we need to activate user's timezone to get access to rendering of timezone aware date and time in templates and forms.

Example of setting current timezone (from Django docs):

from django.utils import timezone

class TimezoneMiddleware(object):
    def process_request(self, request):
        tz = request.session.get('django_timezone')
        if tz:
            timezone.activate(tz)


Main functionality we need for this issue is concentrated in 'django.utils.timezone'.

Templates

Those dates workout is widely supported in templates along with Python code.

# Converting to Paris timezone
{% timezone "Europe/Paris" %}
    Paris time: {{ value }}
{% endtimezone %}

# default date display, like they're actually stored (UTC)
{% localtime off %}
    {{ value }}
{% endlocaltime %}


Migration

  1. Setting settings.USE_TZ = True 
  2. pip install pytz (read farther)
  3. Convert DB datetime values into UTC time. (If it is different) 


Now your code supports timezones. You have to repair some old places where Django does not handle it for us. We have to convert naive dates into timezone-aware. Otherwise you can get wired bugs while changing Winter/Somer time. To complete the migration you have to use 'django.utils.timezone' and debug places where dates in new format are compared to "new" one's.

pytz

Library that handles handy timezone workout in python. Olson database and handy API are included for different timezone calculations. Despite it is optional in Django 1.4 developers recommend to include it. It helps Framework not to guess default timezones while calculating time and provides timezone list to render for users.

Conclusion

Those new features make me proud user of this framework and simplify many holes that I had to handle myself. E.g. with hosting app using Australia/Sydney Timezone and working with it in Europe/Kiev. ;)

Comments

  1. lurii, this is a great blog. It really helped me to set the timezones up. But I have a problem. Even though I see the list of time zones and submit a different timezone, my default timezone remains selected. Do you have any idea why?

    This is the selector in my base.html: http://pastebin.com/TFFSJUAc
    This is my view: http://pastebin.com/0D97Q6ni
    This is the middleware: http://pastebin.com/DVEhzHtp
    and this is the url: (r'^timezone/', set_timezone),

    In my template I even have added {% load tz %} {% get_current_timezone as TIME_ZONE %}{{TIME_ZONE}} and I still see all the time "Europe/London", no matter what I select. What could have gone wrong please? Thank you for your help

    ReplyDelete
    Replies
    1. What timezone is specified in your settings.py?

      Delete
  2. I know time has moved on a bit since this post, but I just came across the problem of determining the user's timezone.

    I couldn't find an existing app for this, so I put together one which uses JS + getTimezoneOffset:

    https://github.com/adamcharnock/django-tz-detect

    Hopefully that will be of use to someone!

    ReplyDelete
  3. I've produced an even easier approach which uses a geolocation database: https://github.com/Miserlou/django-easy-timezones

    ReplyDelete

Post a Comment

Popular posts from this blog

Pretty git Log

SO you dislike git log output in console like me and do not use it... Because it looks like so: How about this one? It's quite easy... Just type: git log - - graph - - pretty = format : '%Cred%h%Creset -%C ( yellow ) %d%Creset %s %Cgreen ( %cr) %C ( bold blue ) <%an>%Creset' - - abbrev - commit - - It may be hard to enter such an easy command every time. Let's make an alias instead... Copypaste this to your terminal: git config --global alias.lg "log --color --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit --" And use simple command to see this pretty log instead: git lg Now in case you want to see lines that changed use: git lg - p In order for this command to work remove  the -- from the end of the alias. May the code be with you! NOTE: this article is a rewritten copy of  http://coderwall.com/p/euwpig?i=3&p=1&t=git   and have b...

Django: Resetting Passwords (with internal tools)

I have had a task recently. It was about adding a forms/mechanism for resetting a password in our Django based project. We have had our own registration system ongoing... It's a corporate sector project. So you can not go and register yourself. Admins (probably via LDAP sync) will register your email/login in system. So you have to go there and only set yourself a password. For security reasons you can not register. One word. First I've tried to find standart decision. From reviewed by me were: django-registration and django password-reset . These are nice tools to install and give it a go. But I've needed a more complex decision. And the idea was that own bicycle is always better. So I've thought of django admin and that it has all the things you need to do this yourself in no time. (Actually it's django.contrib.auth part of django, but used out of the box in Admin UI) You can find views you need for this in there. they are: password_reset password_reset_...

Vagrant error: * Unknown configuration section 'hostmanager'.

Sometimes you get a vagrant environment or boilerplate with a Vagrantfile config in there and do a vagrant up command. And see some errors. like this: There are errors in the configuration of this machine . Please fix the following errors and try again : Vagrant: * Unknown configuration section 'hostmanager'. To fix this one needs: $ vagrant plugin install vagrant - hostmanager Installing the ' vagrant-hostmanager ' plugin . This can take a few minutes . . . Fetching : vagrant - hostmanager - 1.8 .6 . gem ( 100 % ) Installed the plugin ' vagrant-hostmanager (1.8.6) ' ! So command to fix this as follows: vagrant plugin install vagrant-hostmanager