Как стать автором
Обновить

Автоматическое определение часового пояса пользователя

Время на прочтение5 мин
Количество просмотров14K
Мужик сидит, слушает радио.
— В Москве полночь, в Благовещенске 6 утра, во Владивостоке, Хабаровске, Южно-Сахалинске 7, в Магадане 8, в Петропавловске-Камчатском 9 часов.
Мужик сидит, сидит, потом встаёт, и с некоторым сожалением произносит:
— Эх, ну и бардак же у нас в стране!

Текст перепечатан с аудиозаписи позывных «Маяка».
Для справки: в Петропавловске-Камчатском теперь UTC+11 (летом UTC+12), поэтому теперь в полночь по московскому времени там было бы 8 часов, а не 9.


Во многих местах на сайтах отображается время. И во многих случаях лучше всего отображать не время по Гринвичу, не время на сервере, а время в часовом поясе пользователя.

Часто предлагается выбрать свой часовой пояс из огромного списка возможных вариантов. Конечно, возможность приятная, но удобнее, если сайт может определить часовой пояс пользователя сам. А сделать это, как можно догадаться, совсем несложно — достаточно получить локальное время и отступ от UTC с помощью JavaScript и передать этот отступ на сервер с помощью XMLHttpRequest.


Вперёд, попробуем



Создадим новый Django-проект. Назовём его tep — timezone experiment project.

django-admin startproject tep

Добавим новое приложение.

cd tep/
python manage.py startapp whattimeisit

Теперь откроем settings.py и добавим в начале:
import os
SITE_ROOT = os.path.dirname(os.path.realpath(__file__))

Теперь укажем путь до директории шаблонов:
TEMPLATE_DIRS = (
    os.path.join(SITE_ROOT, 'templates'),
)

И добавим наше приложение в список установленных:
INSTALLED_APPS = (
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.sites',
    'django.contrib.messages',
    # Uncomment the next line to enable the admin:
    # 'django.contrib.admin',
    'whattimeisit',
)

А также укажем базу данных:
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3', # Add 'postgresql_psycopg2', 'postgresql', 'mysql', 'sqlite3' or 'oracle'.
        'NAME': 'database', # Or path to database file if using sqlite3.
    }
}

И, конечно же, создадим директорию шаблонов, которую мы указали в settings.py.

mkdir templates/

И выполним syncdb.

python manage.py syncdb

В директории шаблонов создадим шаблон index.html.

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Время</title>
<script type="text/javascript" src="/static/jquery-1.4.2.min.js"></script>
<script type="text/javascript">
 $(document).ready(function(){
  var time_zone = (new Date().getTimezoneOffset()/60)*(-1);
  var dateoffset = time_zone*60*60*1000;
  $('span.please_parse').each(function() {
    var date = new Date($(this).text());
    date.setTime(date.getTime() + dateoffset);
    $(this).text(date.toLocaleString());
  });
  $.post('/please_set_timezone', { 'offset': time_zone });
 });
</script>
</head>
<body>
    <p>
    {% if local_time %}
    Сейчас <b>{{ local_time }}</b>.
    {% else %}
    Сейчас <b><span class="please_parse">{{ time }}</span></b>.
    {% endif %}
    </p>
</body>
</html>


Теперь создадим директорию для статических файлов.

mkdir media/

urls.py в итоге вот такой:

from django.conf.urls.defaults import *
import os
from settings import SITE_ROOT

# Uncomment the next two lines to enable the admin:
# from django.contrib import admin
# admin.autodiscover()

urlpatterns = patterns('',
    # Example:
    # (r'^tep/', include('tep.foo.urls')),

    # Uncomment the admin/doc line below and add 'django.contrib.admindocs'
    # to INSTALLED_APPS to enable admin documentation:
    # (r'^admin/doc/', include('django.contrib.admindocs.urls')),

    # Uncomment the next line to enable the admin:
    # (r'^admin/', include(admin.site.urls)),

    (r'^static/(?P<path>.*)$', 'django.views.static.serve', {'document_root': os.path.join(SITE_ROOT, 'media')}),

    (r'^$', 'whattimeisit.views.index'),
    (r'^please_set_timezone$', 'whattimeisit.views.please_set_timezone'),
)


В директорию media/ нужно загрузить jQuery. Я сохранил в эту директорию jquery-1.4.2.min.js.

А views.py получился вот такой:

# Create your views here.

from django.http import HttpResponse, HttpResponseRedirect
from django.core.urlresolvers import reverse
from django.shortcuts import render_to_response
from datetime import datetime
from datetime import timedelta

def please_set_timezone(request):
    if request.is_ajax():
        timezone_offset = request.POST.get('offset', False)
        if timezone_offset:
            request.session['timezone_offset'] = timezone_offset
        message = "OK"
        return HttpResponse(message)
    return HttpResponseRedirect(reverse('whattimeisit.views.index'))

def index(request):
    time = datetime.utcnow()
    timezone_offset = request.session.get('timezone_offset', False)
    if timezone_offset:
        offset = timedelta(hours=int(timezone_offset))
        local_time = time+offset
        local_time_string = local_time.strftime("%d.%m.%Y %H:%M:%S")
    else:
        local_time_string = False
    time_string = time.strftime("%m/%d/%Y %H:%M:%S")
    return render_to_response("index.html", {'time': time_string, 'local_time': local_time_string,})


Вот, собственно, и готово. Теперь можно запустить сервер и посмотреть результат.

python manage.py runserver

А вот сходу ещё идея. На основе автоматически определённого часового пояса сокращать список стран и городов для выбора. Разумеется, с возможностью показа полного списка — поскольку, по-первых, автоматика может ошибаться (если, например, время на компьютере пользователя установлено неправильно), во-вторых, пользователь может просто по каким-то причинам временно находиться в другой стране или в другом городе.

Этот метод хорош тем, что даже если у пользователя не принимаются cookies, у него всё равно будет показываться время в его часовом поясе с помощью JavaScript. Если же cookies у него включены, то со второй страницы сервер сам будет выдавать ему его локальную дату.
Теги:
Хабы:
+29
Комментарии35

Публикации

Истории

Ближайшие события

Weekend Offer в AliExpress
Дата20 – 21 апреля
Время10:00 – 20:00
Место
Онлайн
Конференция «Я.Железо»
Дата18 мая
Время14:00 – 23:59
Место
МоскваОнлайн