AJAX & JavaScript

Automatic user’s timezone determination with JavaScript and django-timezones 3

There is a nice solution to manage timezones: django-timezones. It allows you to store a user’s timezone in his profile and show time in his timezone. How do we determine a user timezone by not asking him to fill in a profile manually? One of the ways is a client script that can get timezone offset in minutes. Lets use it to automatically set timezone on page load using ajax request:

$(document).ready(function(){
    $.post("/ajax_set_timezone/",
           {timezone_offset: new Date().getTimezoneOffset()});
});

Now there is problem: converting timezone offset to timezone on server side. We can iterate over all timezones and find first, which fits in a specified time offset. It will be a wrong timezone (in most cases), but correct time offset (which is more important for us):

from django import http

from models import UserProfile

import pytz
import datetime

def ajax_set_timezone(request):
    if not request.user.is_authenticated():
        return http.HttpResponseBadRequest()

    # Load or create user profile.
    try:
        profile = request.user.get_profile()
    except UserProfile.DoesNotExist:
        profile = request.user.userprofile_set.create()

    if request.method == "POST":
        if "timezone_offset" in request.POST:
            # Create timezone offset in required format.
            # Javascript sends offset in minutes. -120 = GMT+0200
            try:

                minutes = int(request.POST["timezone_offset"])
            except (ValueError, TypeError):
                return http.HttpResponseBadRequest()

            if minutes < 0:
                minutes = -minutes
                minus = True
            else:
                minus = False

            min = minutes % 60
            hours = (minutes - min) / 60
            offset = "%s%02d%02d" % (minus and "+" or "-", hours, min)

            # Check if timezone not changed.
            now = datetime.datetime.now(pytz.timezone(profile.timezone))
            if now.strftime("%z") == offset:
                return http.HttpResponse("ok")

            # This is only method I found to determine timezone by offset.
            for tz in pytz.common_timezones:
                now = datetime.datetime.now(pytz.timezone(tz))
                if now.strftime("%z") == offset:
                    profile.timezone = tz
                    profile.save()
                    return http.HttpResponse("ok")

    return http.HttpResponseBadRequest()

After successful execution this view will set timezone to user’s profile.

In this example user profile model should look like:

from django.db import models
from django.contrib.auth.models import User

from timezones.fields import TimeZoneField

class UserProfile(models.Model):
    user = models.ForeignKey(User, unique=True)

    timezone = TimeZoneField()

To make user.get_profile() working we also need to set profile module in django settings file:

AUTH_PROFILE_MODULE = "app_name.UserProfile"

3 Responses to “Automatic user’s timezone determination with JavaScript and django-timezones”

  1. The layout for your site is a bit off in Opera. Even So I like your site. I may have to install a “normal” browser just to enjoy it. :)

  2. Hal says:

    Very nice Nazar. Thanks for this helpful tip.

    How do you get the admin panels to display a DateTime field with the date and time in the user’s timezone?

    For example:

    class Article(models.Model):
    publish_datetime = models.DateTimeField(
    _(”Publish at”),
    default=datetime.now,
    blank=True
    )

    and then in the back end, will the date time be stored in a common timezone so that, in this case, articles will be ordered correctly?

    I notice the datetime field in the admin also doesn’t mention the timezone. Maybe the admin field needs to be modified to include a timezone selector?

  3. Nazar Leush says:

    Try dig django-timezones documentation. There is LocalizedDateTimeField field.

    To store UTC time and showing user’s time I used custom forms and “timezones.utils.adjust_datetime_to_timezone” function in django-timezones app. So when user saves some date I converted it to UTC and vice versa.

Leave a Reply