Spec-Zone.ru › Django 1.8

Часовые пояса

Обзор

При включённой поддержке часовых поясов Django хранит информацию о датах и временах в формате UTC в базе данных, использует объекты datetime с учётом часового пояса внутри и преобразует их для пользователя в его часовой пояс в шаблонах и формах.

Это удобно, если ваши пользователи находятся в разных часовых поясах и вы хотите отображать информацию о датах и временах в соответствии с местным временем каждого пользователя.

Даже если ваш веб-сайт доступен только в одном часовом поясе, всё равно рекомендуется хранить данные в UTC в базе данных. Одна из основных причин — это летнее время (DST). Многие страны используют систему DST, где время переводится вперёд весной и назад осенью. Если вы работаете с местным временем, вы, скорее всего, столкнётесь с ошибками дважды в год, когда происходят эти переходы. (Документация pytz подробно обсуждает эти проблемы.) Это, вероятно, не важно для вашего блога, но это проблема, если вы переплачиваете или недоплачиваете клиентам на один час дважды в год, каждый год. Решением этой проблемы является использование UTC в коде и использование местного времени только при взаимодействии с конечными пользователями.

Поддержка часовых поясов по умолчанию отключена. Чтобы включить её, установите USE_TZ = True в файле настроек. Установка pytz крайне рекомендуется, но может быть необязательной в зависимости от вашего конкретного бэкенда базы данных, операционной системы и часового пояса. Если вы столкнётесь с ошибкой при запросе дат или времён, попробуйте установить её, прежде чем сообщать об ошибке. Это так же просто, как:

$ pip install pytz

Примечание

Файл настроек по умолчанию settings.py созданный django-admin startproject включает USE_TZ = True для удобства.

Примечание

Также есть независимая, но связанная настройка USE_L10N, которая управляет тем, активирует ли Django локализацию форматов. Подробнее см. Локализация форматов.

Если вы столкнулись с конкретной проблемой, начните с FAQ по часовым поясам.

Концепции

Простые и осознанные объекты datetime

Объекты datetime.datetime Python имеют атрибут tzinfo, который может быть использован для хранения информации о часовом поясе, представленной как экземпляр подкласса datetime.tzinfo. Если этот атрибут установлен и описывает смещение, объект datetime является осознанным. В противном случае он простой.

Вы можете использовать is_aware() и is_naive() для определения того, являются ли даты и время осознанными или простыми.

При отключённой поддержке часовых поясов Django использует простые объекты datetime в местном времени. Это просто и достаточно для многих случаев использования. В этом режиме, чтобы получить текущее время, вы бы написали:

import datetime

now = datetime.datetime.now()

При включённой поддержке часовых поясов (USE_TZ=True), Django использует осознанные объекты datetime с учётом часового пояса. Если ваш код создаёт объекты datetime, они тоже должны быть осознанными. В этом режиме пример выше становится:

from django.utils import timezone

now = timezone.now()

Предупреждение

Работа с осознанными объектами datetime не всегда интуитивна. Например, аргумент tzinfo стандартного конструктора datetime не работает надёжно для часовых поясов с летним временем. Использование UTC обычно безопасно; если вы используете другие часовые пояса, вы должны внимательно изучить документацию pytz.

Примечание

Объекты datetime.time Python также имеют атрибут tzinfo, а PostgreSQL имеет соответствующий тип time with time zone. Однако, как говорится в документации PostgreSQL, этот тип «обладает свойствами, которые приводят к сомнительной полезности».

Django поддерживает только простые объекты времени и выведет исключение, если вы попытаетесь сохранить осознанный объект времени, так как часовой пояс для времени без связанной даты не имеет смысла.

Интерпретация простых объектов datetime

Когда USE_TZ True, Django всё ещё принимает простые объекты datetime, чтобы сохранить обратную совместимость. Когда слой базы данных получает такой объект, он пытается сделать его осознанным, интерпретируя его в установленном по умолчанию часовом поясе, и выводит предупреждение.

К сожалению, во время переходов на летнее время некоторые даты и времена не существуют или являются неоднозначными. В таких ситуациях pytz выводит исключение. Другие реализации tzinfo, такие как местный часовой пояс, используемый в качестве резервного варианта, когда pytz не установлен, могут выводить исключение или возвращать неточные результаты. Именно поэтому при включённой поддержке часовых поясов вы всегда должны создавать осознанные объекты datetime.

На практике это редко является проблемой. Django предоставляет вам осознанные объекты datetime в моделях и формах, и чаще всего новые объекты datetime создаются из существующих с помощью арифметики timedelta. Единственным объектом datetime, который часто создаётся в коде приложения, является текущее время, и timezone.now() автоматически делает всё правильно.

Установленный по умолчанию часовой пояс и текущий часовой пояс

Установленный по умолчанию часовой пояс — это часовой пояс, определённый настройкой TIME_ZONE.

Текущий часовой пояс — это часовой пояс, используемый для отображения.

Вы должны установить текущий часовой пояс на фактический часовой пояс конечного пользователя с помощью activate(). В противном случае используется установленный по умолчанию часовой пояс.

Примечание

Как объясняется в документации TIME_ZONE, Django устанавливает переменные окружения, чтобы процесс выполнялся в установленном по умолчанию часовом поясе. Это происходит независимо от значения USE_TZ и от текущего часового пояса.

Когда USE_TZ True, это полезно для сохранения обратной совместимости с приложениями, которые всё ещё полагаются на местное время. Однако, как объяснялось выше, это не совсем надёжно, и вы всегда должны работать с осознанными датами и временами в UTC в своём коде. Например, используйте utcfromtimestamp() вместо fromtimestamp() — и не забудьте установить tzinfo на utc.

Выбор текущего часового пояса

Текущий часовой пояс эквивалентен текущему локали для переводов. Однако нет эквивалента HTTP-заголовка Accept-Language, который Django мог бы использовать для автоматического определения часового пояса пользователя. Вместо этого Django предоставляет функции выбора часового пояса. Используйте их для построения логики выбора часового пояса, которая имеет смысл для вас.

Большинство веб-сайтов, которые заботятся о часовых поясах, просто спрашивают пользователей, в каком часовом поясе они живут, и хранят эту информацию в профиле пользователя. Для анонимных пользователей они используют часовой пояс своей основной аудитории или UTC. pytz предоставляет помощники, такие как список часовых поясов по странам, которые вы можете использовать для предварительного выбора наиболее вероятных вариантов.

Вот пример, который сохраняет текущий часовой пояс в сессии. (Он полностью пропускает обработку ошибок для простоты.)

Добавьте следующий middleware в MIDDLEWARE_CLASSES:

import pytz

from django.utils import timezone

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

Создайте представление, которое может установить текущий часовой пояс:

from django.shortcuts import redirect, render

def set_timezone(request):
    if request.method == 'POST':
        request.session['django_timezone'] = request.POST['timezone']
        return redirect('/')
    else:
        return render(request, 'template.html', {'timezones': pytz.common_timezones})

Включите форму в template.html, которая будет POST в это представление:

{% load tz %}
{% get_current_timezone as TIME_ZONE %}
<form action="{% url 'set_timezone' %}" method="POST">
    {% csrf_token %}
    <label for="timezone">Time zone:</label>
    <select name="timezone">
        {% for tz in timezones %}
        <option value="{{ tz }}"{% if tz == TIME_ZONE %} selected="selected"{% endif %}>{{ tz }}</option>
        {% endfor %}
    </select>
    <input type="submit" value="Set" />
</form>

Часовые пояса в формах

Когда вы включаете поддержку часовых поясов, Django интерпретирует даты и время, введённые в формах, в текущем часовом поясе и возвращает осознанные объекты datetime в cleaned_data.

Если текущая часовая зона вызывает исключение для дат и времени, которые не существуют или являются неоднозначными из-за перехода на летнее время (часовые зоны, предоставленные pytz, делают это), такие даты и время будут сообщаться как недопустимые значения.

Часовые зоны в шаблонах

При включении поддержки часовых зон Django преобразует объекты datetime с учетом часовых поясов в текущую часовую зону при их отображении в шаблонах. Это очень похоже на форматирование локализации.

Предупреждение

Django не преобразует объекты datetime без учета часовых поясов, потому что они могут быть неоднозначными, и потому что ваш код никогда не должен создавать объекты datetime без учета часовых поясов, когда включена поддержка часовых поясов. Однако вы можете принудительно выполнить преобразование с помощью фильтров шаблонов, описанных ниже.

Преобразование в местное время не всегда уместно — вы можете генерировать выходные данные для компьютеров, а не для людей. Следующие фильтры и теги, предоставленные библиотекой тегов шаблонов tz, позволяют вам контролировать преобразования часовых зон.

Теги шаблонов

localtime

Включает или отключает преобразование объектов datetime с учетом часовых поясов в текущую часовую зону в содержащемся блоке.

Этот тег имеет точно такие же эффекты, как и настройка USE_TZ с точки зрения движка шаблонов. Это позволяет более точно управлять преобразованием.

Чтобы активировать или деактивировать преобразование для блока шаблона, используйте:

{% load tz %}

{% localtime on %}
    {{ value }}
{% endlocaltime %}

{% localtime off %}
    {{ value }}
{% endlocaltime %}

Примечание

Значение USE_TZ не учитывается внутри блока {% localtime %}.

timezone

Устанавливает или сбрасывает текущую часовую зону в содержащемся блоке. Когда текущая часовая зона сброшена, применяется значение по умолчанию.

{% load tz %}

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

{% timezone None %}
    Server time: {{ value }}
{% endtimezone %}

get_current_timezone

Вы можете получить имя текущей часовой зоны, используя тег get_current_timezone:

{% get_current_timezone as TIME_ZONE %}

Если вы включите процессор контекста django.template.context_processors.tz, каждый RequestContext будет содержать переменную TIME_ZONE со значением get_current_timezone().

Фильтры шаблонов

Эти фильтры принимают как объекты datetime с учетом часовых поясов, так и без учета.

В целях преобразования они предполагают, что объекты datetime без учета часовых поясов находятся в часовой зоне по умолчанию. Они всегда возвращают объекты datetime с учетом часовых поясов.

localtime

Принудительно преобразует одно значение в текущую часовую зону.

Например:

{% load tz %}

{{ value|localtime }}

utc

Принудительно преобразует одно значение в UTC.

Например:

{% load tz %}

{{ value|utc }}

timezone

Принудительно преобразует одно значение в произвольную часовую зону.

Аргументом должен быть экземпляр подкласса tzinfo или имя часовой зоны. Если это имя часовой зоны, требуется pytz.

Например:

{% load tz %}

{{ value|timezone:"Europe/Paris" }}

Руководство по миграции

Вот как мигрировать проект, который был начат до того, как Django поддерживал часовые пояса.

База данных

PostgreSQL

База данных PostgreSQL хранит даты и время как timestamp with time zone. На практике это означает, что она преобразует даты и время из часовой зоны подключения в UTC при сохранении и из UTC в часовую зону подключения при извлечении.

Следовательно, если вы используете PostgreSQL, вы можете свободно переключаться между USE_TZ = False и USE_TZ = True. Часовая зона подключения к базе данных будет установлена в TIME_ZONE или UTC соответственно, чтобы Django в любом случае получал правильные даты и время. Вам не нужно выполнять никаких преобразований данных.

Другие базы данных

Другие базы данных хранят даты и время без информации о часовом поясе. Если вы переключаетесь с USE_TZ = False на USE_TZ = True, вы должны преобразовать данные из местного времени в UTC — что не является детерминированным, если в вашем местном времени есть летнее время.

Код

Первый шаг — добавить USE_TZ = True в файл настроек и установить pytz (если это возможно). На этом этапе все должно работать в основном. Если вы создаете объекты datetime без учета часовых поясов в своем коде, Django делает их учитывающими часовой пояс при необходимости.

Однако эти преобразования могут не удаваться во время перехода на летнее время, а это означает, что вы еще не получаете всех преимуществ поддержки часовых поясов. Кроме того, вы, вероятно, столкнетесь с несколькими проблемами, потому что невозможно сравнить объект datetime без учета часовых поясов с объектом datetime с учетом часовых поясов. Поскольку Django теперь предоставляет вам объекты datetime с учетом часовых поясов, вы получите исключения всякий раз, когда вы сравниваете datetime, полученное из модели или формы, с объектом datetime без учета часовых поясов, который вы создали в своем коде.

Итак, второй шаг — переписать свой код, где вы создаете объекты datetime, чтобы сделать их учитывающими часовой пояс. Это можно сделать постепенно. django.utils.timezone определяет некоторые удобные вспомогательные функции для совместимого кода: now(), is_aware(), is_naive(), make_aware() и make_naive().

Наконец, чтобы помочь вам найти код, который нужно обновить, Django выводит предупреждение, когда вы пытаетесь сохранить объект datetime без учета часовых поясов в базу данных:

RuntimeWarning: DateTimeField ModelName.field_name received a naive
datetime (2012-01-01 00:00:00) while time zone support is active.

Во время разработки вы можете превратить такие предупреждения в исключения и получить обратный след, добавив следующее в файл настроек:

import warnings
warnings.filterwarnings(
        'error', r"DateTimeField .* received a naive datetime",
        RuntimeWarning, r'django\.db\.models\.fields')

Файлы данных

При сериализации объекта datetime с учетом часовых поясов смещение UTC включается, например:

"2011-09-01T13:20:30+03:00"

Для объекта datetime без учета часовых поясов этого, очевидно, нет:

"2011-09-01T13:20:30"

Для моделей с полями DateTimeField это различие делает невозможным создание файла данных, который работает как с поддержкой часовых поясов, так и без нее.

Файлы данных, сгенерированные с помощью USE_TZ = False, или до Django 1.4, используют формат «без учета часовых поясов». Если ваш проект содержит такие файлы данных, после включения поддержки часовых поясов вы увидите RuntimeWarning при их загрузке. Чтобы избавиться от предупреждений, вы должны преобразовать свои файлы данных в формат «с учетом часовых поясов».

Вы можете перегенерировать файлы данных с помощью loaddata, а затем dumpdata. Или, если они достаточно маленькие, вы можете просто отредактировать их, чтобы добавить смещение UTC, соответствующее вашей TIME_ZONE, в каждую сериализованную дату и время.

ЧАВО

Настройка

  1. Мне не нужны несколько часовых поясов. Нужно ли включить поддержку часовых поясов?

    Да. При включённой поддержке часовых поясов Django использует более точную модель местного времени. Это защищает вас от скрытых и невоспроизводимых ошибок, связанных с переходом на летнее/зимнее время.

    В этом отношении часовые пояса сопоставимы с unicode в Python. Сначала это сложно. Появляются ошибки кодирования и декодирования. Затем вы изучаете правила. И некоторые проблемы исчезают — вы больше никогда не получите повреждённый вывод, когда ваше приложение получает входные данные, не являющиеся ASCII.

    При включении поддержки часовых поясов вы столкнётесь с некоторыми ошибками, потому что вы используете незаявленные даты и время, в то время как Django ожидает временные метки с указанием часового пояса. Такие ошибки проявляются при запуске тестов и их легко исправить. Вы быстро научитесь избегать некорректных операций.

    С другой стороны, ошибки, вызванные отсутствием поддержки часовых поясов, гораздо сложнее предотвратить, диагностировать и исправить. Всё, что связано с запланированными задачами или арифметикой дат и времени, является кандидатом на скрытые ошибки, которые повлияют на вас только один или два раза в год.

    По этим причинам поддержка часовых поясов включена по умолчанию в новых проектах, и вы должны её сохранять, если у вас нет веской причины этого не делать.

  2. Я включил поддержку часовых поясов. Я в безопасности?

    Возможно. Вы защищены от ошибок, связанных с переходом на летнее/зимнее время, но вы всё ещё можете попасть в затруднение, небрежно превращая незаявленные даты и время во временные метки с указанием часового пояса и наоборот.

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

    Наконец, наша календарная система содержит интересные ловушки для компьютеров:

    >>> import datetime
    >>> def one_year_before(value):       # DON'T DO THAT!
    ...     return value.replace(year=value.year - 1)
    >>> one_year_before(datetime.datetime(2012, 3, 1, 10, 0))
    datetime.datetime(2011, 3, 1, 10, 0)
    >>> one_year_before(datetime.datetime(2012, 2, 29, 10, 0))
    Traceback (most recent call last):
    ...
    ValueError: day is out of range for month
    

    (Чтобы реализовать эту функцию, вы должны решить, является ли 2012-02-29 минус один год 2011-02-28 или 2011-03-01, что зависит от ваших бизнес-требований.)

  3. Нужно ли устанавливать pytz?

    Да. Django придерживается политики не требовать внешних зависимостей, и по этой причине pytz является необязательным. Однако гораздо безопаснее его установить.

    Как только вы активируете поддержку часовых поясов, Django нуждается в определении часового пояса по умолчанию. Когда pytz доступен, Django загружает это определение из базы данных часовых поясов. Это наиболее точное решение. В противном случае он полагается на разницу между местным временем и UTC, как указано операционной системой, для вычисления преобразований. Это менее надёжно, особенно во время перехода на летнее/зимнее время.

    Кроме того, если вы хотите поддерживать пользователей в нескольких часовых поясах, pytz является эталоном для определений часовых поясов.

Устранение неполадок

  1. Моё приложение завершается с ошибкой TypeError: can't compare offset-naive and offset-aware datetimes — в чём проблема?

    Давайте воспроизведём эту ошибку, сравнив незаявленную и заявленную даты и время:

    >>> import datetime
    >>> from django.utils import timezone
    >>> naive = datetime.datetime.utcnow()
    >>> aware = timezone.now()
    >>> naive == aware
    Traceback (most recent call last):
    ...
    TypeError: can't compare offset-naive and offset-aware datetimes
    

    Если вы столкнулись с этой ошибкой, скорее всего, ваш код сравнивает эти две вещи:

    • дата и время, предоставленные Django — например, значение, считанное из формы или поля модели. Поскольку вы включили поддержку часовых поясов, она с указанием часового пояса.
    • дата и время, сгенерированные вашим кодом, которые незаявленные (иначе вы бы не читали это).

    В целом, правильное решение — изменить свой код, чтобы использовать заявленную дату и время вместо незаявленной.

    Если вы пишете подключаемый модуль, который должен работать независимо от значения USE_TZ, вам может быть полезен django.utils.timezone.now(). Эта функция возвращает текущую дату и время в виде незаявленной даты и времени, когда USE_TZ = False и в виде заявленной даты и времени, когда USE_TZ = True. Вы можете добавлять или вычитать datetime.timedelta по мере необходимости.

  2. Я вижу много RuntimeWarning: DateTimeField received a naive datetime (YYYY-MM-DD HH:MM:SS) while time zone support is active — это плохо?

    Когда включена поддержка часовых поясов, уровень базы данных ожидает получить только заявленные даты и время от вашего кода. Это предупреждение появляется, когда он получает незаявленную дату и время. Это указывает на то, что вы не завершили перенос своего кода для поддержки часовых поясов. Обратитесь к руководству по миграции за советами по этому процессу.

    Тем временем, для обратной совместимости дата и время рассматриваются как находящиеся в часовом поясе по умолчанию, что, как правило, и ожидается.

  3. now.date() вчера! (или завтра)

    Если вы всегда использовали незаявленные даты и время, вы, вероятно, считаете, что можете преобразовать дату и время в дату, вызвав её метод date(). Вы также считаете, что date очень похожа на datetime, за исключением того, что она менее точная.

    Ничто из этого неверно в среде с учётом часовых поясов:

    >>> import datetime
    >>> import pytz
    >>> paris_tz = pytz.timezone("Europe/Paris")
    >>> new_york_tz = pytz.timezone("America/New_York")
    >>> paris = paris_tz.localize(datetime.datetime(2012, 3, 3, 1, 30))
    # This is the correct way to convert between time zones with pytz.
    >>> new_york = new_york_tz.normalize(paris.astimezone(new_york_tz))
    >>> paris == new_york, paris.date() == new_york.date()
    (True, False)
    >>> paris - new_york, paris.date() - new_york.date()
    (datetime.timedelta(0), datetime.timedelta(1))
    >>> paris
    datetime.datetime(2012, 3, 3, 1, 30, tzinfo=<DstTzInfo 'Europe/Paris' CET+1:00:00 STD>)
    >>> new_york
    datetime.datetime(2012, 3, 2, 19, 30, tzinfo=<DstTzInfo 'America/New_York' EST-1 day, 19:00:00 STD>)
    

    Как показывает этот пример, у одной и той же даты и времени разная дата в зависимости от часового пояса, в котором она представлена. Но реальная проблема более фундаментальна.

    Дата и время представляют собой точку во времени. Она абсолютна: она не зависит ни от чего. Напротив, дата — это понятие календаря. Это период времени, границы которого зависят от часового пояса, в котором рассматривается дата. Как вы можете видеть, эти два понятия принципиально отличаются, и преобразование даты и времени в дату — это не детерминированная операция.

    Что это значит на практике?

    В общем случае следует избегать преобразования datetime в date. Например, вы можете использовать date фильтр шаблона, чтобы показать только часть даты и времени. Этот фильтр преобразует дату и время в текущий часовой пояс перед форматированием, гарантируя, что результаты отображаются правильно.

    Если вам действительно нужно выполнить преобразование самостоятельно, вы должны убедиться, что дата и время сначала преобразованы в соответствующий часовой пояс. Обычно это будет текущий часовой пояс:

    >>> from django.utils import timezone
    >>> timezone.activate(pytz.timezone("Asia/Singapore"))
    # For this example, we just set the time zone to Singapore, but here's how
    # you would obtain the current time zone in the general case.
    >>> current_tz = timezone.get_current_timezone()
    # Again, this is the correct way to convert between time zones with pytz.
    >>> local = current_tz.normalize(paris.astimezone(current_tz))
    >>> local
    datetime.datetime(2012, 3, 3, 8, 30, tzinfo=<DstTzInfo 'Asia/Singapore' SGT+8:00:00 STD>)
    >>> local.date()
    datetime.date(2012, 3, 3)
    
  4. У меня ошибка “Are time zone definitions for your database and pytz installed?” pytz установлен, так что, наверное, проблема в моей базе данных?

    Если вы используете MySQL, см. раздел Определения часовых поясов в заметках MySQL для получения инструкций по загрузке определений часовых поясов.

Использование

  1. У меня есть строка "2012-02-21 10:28:45" и я знаю, что она в часовом поясе "Europe/Helsinki" . Как я могу превратить её в заявленную дату и время?

    Для этого как раз и предназначен pytz.

    >>> from django.utils.dateparse import parse_datetime
    >>> naive = parse_datetime("2012-02-21 10:28:45")
    >>> import pytz
    >>> pytz.timezone("Europe/Helsinki").localize(naive, is_dst=None)
    datetime.datetime(2012, 2, 21, 10, 28, 45, tzinfo=<DstTzInfo 'Europe/Helsinki' EET+2:00:00 STD>)
    

    Обратите внимание, что localize — это расширение pytz для API tzinfo. Также, вам, возможно, захочется перехватить pytz.InvalidTimeError. В документации pytz содержатся дополнительные примеры. Вы должны ознакомиться с ними, прежде чем пытаться манипулировать заявленными датами и временем.

  2. Как получить местное время в текущем часовом поясе?

    Ну, первый вопрос — вам это действительно нужно?

    Вы должны использовать местное время только при взаимодействии с людьми, а уровень шаблонов предоставляет фильтры и теги для преобразования дат и времени в часовой пояс по вашему выбору.

    Кроме того, Python знает, как сравнивать заявленные даты и время, учитывая смещения от UTC при необходимости. Гораздо проще (и, возможно, быстрее) написать весь код модели и представления в UTC. Итак, в большинстве случаев даты и время в UTC, возвращаемые django.utils.timezone.now(), будут достаточны.

    Однако, для полноты картины, если вам действительно нужно местное время в текущем часовом поясе, вот как вы можете его получить:

    >>> from django.utils import timezone
    >>> timezone.localtime(timezone.now())
    datetime.datetime(2012, 3, 3, 20, 10, 53, 873365, tzinfo=<DstTzInfo 'Europe/Paris' CET+1:00:00 STD>)
    

    В этом примере pytz установлен, а текущий часовой пояс — "Europe/Paris".

  3. Как посмотреть все доступные часовые пояса?

    pytz предоставляет помощники, включая список текущих часовых поясов и список всех доступных часовых поясов — некоторые из которых представляют только исторический интерес.

© Django Software Foundation and individual contributors
Licensed under the BSD License.
https://docs.djangoproject.com/en/1.8/topics/i18n/timezones/

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API