diff options
| author | Aymeric Augustin <aymeric.augustin@m4x.org> | 2011-11-18 13:01:06 +0000 |
|---|---|---|
| committer | Aymeric Augustin <aymeric.augustin@m4x.org> | 2011-11-18 13:01:06 +0000 |
| commit | 9b1cb755a28f020e27d4268c214b25315d4de42e (patch) | |
| tree | 2ff0827176f0eb49defa4ce7ce10164f2fc26e86 /docs | |
| parent | 01f70349c9ef23d6751437dcd57d2efc193b2661 (diff) | |
Added support for time zones. Thanks Luke Plant for the review. Fixed #2626.
For more information on this project, see this thread:
http://groups.google.com/group/django-developers/browse_thread/thread/cf0423bbb85b1bbf
git-svn-id: http://code.djangoproject.com/svn/django/trunk@17106 bcc190cf-cafb-0310-a4f2-bffc1f526a37
Diffstat (limited to 'docs')
| -rw-r--r-- | docs/howto/custom-template-tags.txt | 25 | ||||
| -rw-r--r-- | docs/ref/models/querysets.txt | 13 | ||||
| -rw-r--r-- | docs/ref/settings.txt | 54 | ||||
| -rw-r--r-- | docs/ref/templates/builtins.txt | 63 | ||||
| -rw-r--r-- | docs/ref/utils.txt | 125 | ||||
| -rw-r--r-- | docs/releases/1.4.txt | 53 | ||||
| -rw-r--r-- | docs/topics/cache.txt | 4 | ||||
| -rw-r--r-- | docs/topics/i18n/index.txt | 10 | ||||
| -rw-r--r-- | docs/topics/i18n/timezones.txt | 429 |
9 files changed, 734 insertions, 42 deletions
diff --git a/docs/howto/custom-template-tags.txt b/docs/howto/custom-template-tags.txt index 6b2355e8d0..0b962f8863 100644 --- a/docs/howto/custom-template-tags.txt +++ b/docs/howto/custom-template-tags.txt @@ -347,6 +347,31 @@ function; this syntax is deprecated. return mark_safe(result) initial_letter_filter.needs_autoescape = True +.. _filters-timezones: + +Filters and time zones +~~~~~~~~~~~~~~~~~~~~~~ + +.. versionadded:: 1.4 + +If you write a custom filter that operates on :class:`~datetime.datetime` +objects, you'll usually register it with the ``expects_localtime`` flag set to +``True``: + +.. code-block:: python + + @register.filter(expects_localtime=True) + def businesshours(value): + try: + return 9 <= value.hour < 17 + except AttributeError: + return '' + +When this flag is set, if the first argument to your filter is a time zone +aware datetime, Django will convert it to the current time zone before passing +to your filter when appropriate, according to :ref:`rules for time zones +conversions in templates <time-zones-in-templates>`. + Writing custom template tags ---------------------------- diff --git a/docs/ref/models/querysets.txt b/docs/ref/models/querysets.txt index 68da9c7343..9736d94838 100644 --- a/docs/ref/models/querysets.txt +++ b/docs/ref/models/querysets.txt @@ -546,6 +546,12 @@ Examples:: >>> Entry.objects.filter(headline__contains='Lennon').dates('pub_date', 'day') [datetime.datetime(2005, 3, 20)] +.. warning:: + + When :doc:`time zone support </topics/i18n/timezones>` is enabled, Django + uses UTC in the database connection, which means the aggregation is + performed in UTC. This is a known limitation of the current implementation. + none ~~~~ @@ -1953,6 +1959,13 @@ Note this will match any record with a ``pub_date`` that falls on a Monday (day 2 of the week), regardless of the month or year in which it occurs. Week days are indexed with day 1 being Sunday and day 7 being Saturday. +.. warning:: + + When :doc:`time zone support </topics/i18n/timezones>` is enabled, Django + uses UTC in the database connection, which means the ``year``, ``month``, + ``day`` and ``week_day`` lookups are performed in UTC. This is a known + limitation of the current implementation. + .. fieldlookup:: isnull isnull diff --git a/docs/ref/settings.txt b/docs/ref/settings.txt index 20366e353d..0d91f16821 100644 --- a/docs/ref/settings.txt +++ b/docs/ref/settings.txt @@ -1810,6 +1810,7 @@ Default:: "django.core.context_processors.i18n", "django.core.context_processors.media", "django.core.context_processors.static", + "django.core.context_processors.tz", "django.contrib.messages.context_processors.messages") A tuple of callables that are used to populate the context in ``RequestContext``. @@ -1830,6 +1831,10 @@ of items to be merged into the context. The ``django.core.context_processors.static`` context processor was added in this release. +.. versionadded:: 1.4 + The ``django.core.context_processors.tz`` context processor + was added in this release. + .. setting:: TEMPLATE_DEBUG TEMPLATE_DEBUG @@ -1971,6 +1976,9 @@ Default: ``'America/Chicago'`` .. versionchanged:: 1.2 ``None`` was added as an allowed value. +.. versionchanged:: 1.4 + The meaning of this setting now depends on the value of :setting:`USE_TZ`. + A string representing the time zone for this installation, or ``None``. `See available choices`_. (Note that list of available choices lists more than one on the same line; you'll want to use just @@ -1978,16 +1986,19 @@ one of the choices for a given time zone. For instance, one line says ``'Europe/London GB GB-Eire'``, but you should use the first bit of that -- ``'Europe/London'`` -- as your :setting:`TIME_ZONE` setting.) -Note that this is the time zone to which Django will convert all -dates/times -- not necessarily the timezone of the server. For -example, one server may serve multiple Django-powered sites, each with -a separate time-zone setting. +Note that this isn't necessarily the timezone of the server. For example, one +server may serve multiple Django-powered sites, each with a separate time zone +setting. + +When :setting:`USE_TZ` is ``False``, this is the time zone in which Django will +store all datetimes. When :setting:`USE_TZ` is ``True``, this is the default +time zone that Django will use to display datetimes in templates and to +interpret datetimes entered in forms. -Normally, Django sets the ``os.environ['TZ']`` variable to the time -zone you specify in the :setting:`TIME_ZONE` setting. Thus, all your views -and models will automatically operate in the correct time zone. -However, Django won't set the ``TZ`` environment variable under the -following conditions: +Django sets the ``os.environ['TZ']`` variable to the time zone you specify in +the :setting:`TIME_ZONE` setting. Thus, all your views and models will +automatically operate in this time zone. However, Django won't set the ``TZ`` +environment variable under the following conditions: * If you're using the manual configuration option as described in :ref:`manually configuring settings @@ -2004,7 +2015,6 @@ to ensure your processes are running in the correct environment. environment. If you're running Django on Windows, this variable must be set to match the system timezone. - .. _See available choices: http://www.postgresql.org/docs/8.1/static/datetime-keywords.html#DATETIME-TIMEZONE-SET-TABLE .. setting:: URL_VALIDATOR_USER_AGENT @@ -2043,7 +2053,7 @@ This provides an easy way to turn it off, for performance. If this is set to ``False``, Django will make some optimizations so as not to load the translation machinery. -See also :setting:`USE_L10N` +See also :setting:`LANGUAGE_CODE`, :setting:`USE_L10N` and :setting:`USE_TZ`. .. setting:: USE_L10N @@ -2058,7 +2068,7 @@ A boolean that specifies if localized formatting of data will be enabled by default or not. If this is set to ``True``, e.g. Django will display numbers and dates using the format of the current locale. -See also :setting:`USE_I18N` and :setting:`LANGUAGE_CODE` +See also :setting:`LANGUAGE_CODE`, :setting:`USE_I18N` and :setting:`USE_TZ`. .. note:: @@ -2082,6 +2092,26 @@ When :setting:`USE_L10N` is set to ``True`` and if this is also set to See also :setting:`DECIMAL_SEPARATOR`, :setting:`NUMBER_GROUPING` and :setting:`THOUSAND_SEPARATOR`. +.. setting:: USE_TZ + +USE_TZ +------ + +.. versionadded:: 1.4 + +Default: ``False`` + +A boolean that specifies if datetimes will be timezone-aware by default or not. +If this is set to ``True``, Django will use timezone-aware datetimes internally. +Otherwise, Django will use naive datetimes in local time. + +See also :setting:`TIME_ZONE`, :setting:`USE_I18N` and :setting:`USE_L10N`. + +.. note:: + The default :file:`settings.py` file created by + :djadmin:`django-admin.py startproject <startproject>` includes + ``USE_TZ = True`` for convenience. + .. setting:: USE_X_FORWARDED_HOST USE_X_FORWARDED_HOST diff --git a/docs/ref/templates/builtins.txt b/docs/ref/templates/builtins.txt index 7b305746ab..695a21296b 100644 --- a/docs/ref/templates/builtins.txt +++ b/docs/ref/templates/builtins.txt @@ -2318,8 +2318,45 @@ Value Argument Outputs if no mapping for None is given) ========== ====================== ================================== -Other tags and filter libraries -------------------------------- +Internationalization tags and filters +------------------------------------- + +Django provides template tags and filters to control each aspect of +`internationalization </topics/i18n/index>`_ in templates. They allow for +granular control of translations, formatting, and time zone conversions. + +i18n +^^^^ + +This library allows specifying translatable text in templates. +To enable it, set :setting:`USE_I18N` to ``True``, then load it with +``{% load i18n %}``. + +See :ref:`specifying-translation-strings-in-template-code`. + +l10n +^^^^ + +This library provides control over the localization of values in templates. +You only need to load the library using ``{% load l10n %}``, but you'll often +set :setting:`USE_L10N` to ``True`` so that localization is active by default. + +See :ref:`topic-l10n-templates`. + +tz +^^ + +.. versionadded:: 1.4 + +This library provides control over time zone conversions in templates. +Like ``l10n``, you only need to load the library using ``{% load tz %}``, +but you'll usually also set :setting:`USE_TZ` to ``True`` so that conversion +to local time happens by default. + +See :ref:`time-zones-in-templates`. + +Other tags and filters libraries +-------------------------------- Django comes with a couple of other template-tag libraries that you have to enable explicitly in your :setting:`INSTALLED_APPS` setting and enable in your @@ -2348,28 +2385,6 @@ django.contrib.webdesign A collection of template tags that can be useful while designing a Web site, such as a generator of Lorem Ipsum text. See :doc:`/ref/contrib/webdesign`. -i18n -^^^^ - -Provides a couple of templatetags that allow specifying translatable text in -Django templates. It is slightly different from the libraries described -above because you don't need to add any application to the -:setting:`INSTALLED_APPS` setting but rather set :setting:`USE_I18N` to True, -then loading it with ``{% load i18n %}``. - -See :ref:`specifying-translation-strings-in-template-code`. - -l10n -^^^^ - -Provides a couple of templatetags that allow control over the localization of -values in Django templates. It is slightly different from the libraries -described above because you don't need to add any application to the -:setting:`INSTALLED_APPS`; you only need to load the library using -``{% load l10n %}``. - -See :ref:`topic-l10n-templates`. - static ^^^^^^ diff --git a/docs/ref/utils.txt b/docs/ref/utils.txt index 0d6e9c6b61..9a9adba0d8 100644 --- a/docs/ref/utils.txt +++ b/docs/ref/utils.txt @@ -131,6 +131,41 @@ results. Instead do:: SortedDict([('b', 1), ('a', 2), ('c', 3)]) +``django.utils.dateparse`` +========================== + +.. versionadded:: 1.4 + +.. module:: django.utils.dateparse + :synopsis: Functions to parse datetime objects. + +The functions defined in this module share the following properties: + +- They raise :exc:`ValueError` if their input is well formatted but isn't a + valid date or time. +- They return ``None`` if it isn't well formatted at all. +- They accept up to picosecond resolution in input, but they truncate it to + microseconds, since that's what Python supports. + +.. function:: parse_date(value) + + Parses a string and returns a :class:`datetime.date`. + +.. function:: parse_time(value) + + Parses a string and returns a :class:`datetime.time`. + + UTC offsets aren't supported; if ``value`` describes one, the result is + ``None``. + +.. function:: parse_datetime(value) + + Parses a string and returns a :class:`datetime.datetime`. + + UTC offsets are supported; if ``value`` describes one, the result's + ``tzinfo`` attribute is a :class:`~django.utils.tzinfo.FixedOffset` + instance. + ``django.utils.encoding`` ========================= @@ -573,6 +608,96 @@ For a complete discussion on the usage of the following see the so by translating the Django translation tags into standard gettext function invocations. +.. _time-zone-selection-functions: + +``django.utils.timezone`` +========================= + +.. versionadded:: 1.4 + +.. module:: django.utils.timezone + :synopsis: Timezone support. + +.. data:: utc + + :class:`~datetime.tzinfo` instance that represents UTC. + +.. function:: get_default_timezone() + + Returns a :class:`~datetime.tzinfo` instance that represents the + :ref:`default time zone <default-current-time-zone>`. + +.. function:: get_default_timezone_name() + + Returns the name of the :ref:`default time zone + <default-current-time-zone>`. + +.. function:: get_current_timezone() + + Returns a :class:`~datetime.tzinfo` instance that represents the + :ref:`current time zone <default-current-time-zone>`. + +.. function:: get_current_timezone_name() + + Returns the name of the :ref:`current time zone + <default-current-time-zone>`. + +.. function:: activate(timezone) + + Sets the :ref:`current time zone <default-current-time-zone>`. The + ``timezone`` argument must be an instance of a :class:`~datetime.tzinfo` + subclass or, if pytz_ is available, a time zone name. + +.. function:: deactivate() + + Unsets the :ref:`current time zone <default-current-time-zone>`. + +.. function:: override(timezone) + + This is a Python context manager that sets the :ref:`current time zone + <default-current-time-zone>` on entry with :func:`activate()`, and restores + the previously active time zone on exit. If the ``timezone`` argument is + ``None``, the :ref:`current time zone <default-current-time-zone>` is unset + on entry with :func:`deactivate()` instead. + +.. function:: aslocaltime(value, use_tz=None) + + This function is used by the template engine to convert datetimes to local + time where appropriate. + +.. function:: now() + + Returns an aware or naive :class:`~datetime.datetime` that represents the + current point in time when :setting:`USE_TZ` is ``True`` or ``False`` + respectively. + +.. function:: is_aware(value) + + Returns ``True`` if ``value`` is aware, ``False`` if it is naive. This + function assumes that ``value`` is a :class:`~datetime.datetime`. + +.. function:: is_naive(value) + + Returns ``True`` if ``value`` is naive, ``False`` if it is aware. This + function assumes that ``value`` is a :class:`~datetime.datetime`. + +.. function:: make_aware(value, timezone) + + Returns an aware :class:`~datetime.datetime` that represents the same + point in time as ``value`` in ``timezone``, ``value`` being a naive + :class:`~datetime.datetime`. + + This function can raise an exception if ``value`` doesn't exist or is + ambiguous because of DST transitions. + +.. function:: make_naive(value, timezone) + + Returns an naive :class:`~datetime.datetime` that represents in + ``timezone`` the same point in time as ``value``, ``value`` being an + aware :class:`~datetime.datetime` + +.. _pytz: http://pytz.sourceforge.net/ + ``django.utils.tzinfo`` ======================= diff --git a/docs/releases/1.4.txt b/docs/releases/1.4.txt index 49284fb90b..46527da581 100644 --- a/docs/releases/1.4.txt +++ b/docs/releases/1.4.txt @@ -409,7 +409,6 @@ If the same code is imported inconsistently (some places with the project prefix, some places without it), the imports will need to be cleaned up when switching to the new ``manage.py``. - Improved WSGI support ~~~~~~~~~~~~~~~~~~~~~ @@ -427,6 +426,25 @@ callable :djadmin:`runserver` uses. (The :djadmin:`runfcgi` management command also internally wraps the WSGI callable configured via :setting:`WSGI_APPLICATION`.) +Support for time zones +~~~~~~~~~~~~~~~~~~~~~~ + +Django 1.4 adds :ref:`support for time zones <time-zones>`. When it's enabled, +Django stores date and time information in UTC in the database, uses time +zone-aware datetime objects internally, and translates them to the end user's +time zone in templates and forms. + +Reasons for using this feature include: + +- Customizing date and time display for users around the world. +- Storing datetimes in UTC for database portability and interoperability. + (This argument doesn't apply to PostgreSQL, because it already stores + timestamps with time zone information in Django 1.3.) +- Avoiding data corruption problems around DST transitions. + +Time zone support in enabled by default in new projects created with +:djadmin:`startproject`. If you want to use this feature in an existing +project, there is a :ref:`migration guide <time-zones-migration-guide>`. Minor features ~~~~~~~~~~~~~~ @@ -616,6 +634,39 @@ immediately raise a 404. Additionally redirects returned by flatpages are now permanent (301 status code) to match the behavior of the :class:`~django.middleware.common.CommonMiddleware`. +Serialization of :class:`~datetime.datetime` and :class:`~datetime.time` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +As a consequence of time zone support, and according to the ECMA-262 +specification, some changes were made to the JSON serializer: + +- It includes the time zone for aware datetime objects. It raises an exception + for aware time objects. +- It includes milliseconds for datetime and time objects. There is still + some precision loss, because Python stores microseconds (6 digits) and JSON + only supports milliseconds (3 digits). However, it's better than discarding + microseconds entirely. + +The XML serializer was also changed to use ISO8601 for datetimes. The letter +``T`` is used to separate the date part from the time part, instead of a +space. Time zone information is included in the ``[+-]HH:MM`` format. + +The serializers will dump datetimes in fixtures with these new formats. They +can still load fixtures that use the old format. + +``supports_timezone`` changed to ``False`` for SQLite +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The database feature ``supports_timezone`` used to be ``True`` for SQLite. +Indeed, if you saved an aware datetime object, SQLite stored a string that +included an UTC offset. However, this offset was ignored when loading the value +back from the database, which could corrupt the data. + +In the context of time zone support, this flag was changed to ``False``, and +datetimes are now stored without time zone information in SQLite. When +:setting:`USE_TZ` is ``False``, if you attempt to save an aware datetime +object, Django raises an exception. + `COMMENTS_BANNED_USERS_GROUP` setting ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/docs/topics/cache.txt b/docs/topics/cache.txt index a3aac74b76..99d764b60d 100644 --- a/docs/topics/cache.txt +++ b/docs/topics/cache.txt @@ -502,7 +502,9 @@ cache multilingual sites without having to create the cache key yourself. .. versionchanged:: 1.4 -This also happens when :setting:`USE_L10N` is set to ``True``. +Cache keys also include the active :term:`language <language code>` when +:setting:`USE_L10N` is set to ``True`` and the :ref:`current time zone +<default-current-time-zone>` when :setting:`USE_TZ` is set to ``True``. __ `Controlling cache: Using other headers`_ diff --git a/docs/topics/i18n/index.txt b/docs/topics/i18n/index.txt index 4e2c9c345c..25ec8392de 100644 --- a/docs/topics/i18n/index.txt +++ b/docs/topics/i18n/index.txt @@ -8,6 +8,7 @@ Internationalization and localization translation formatting + timezones Overview ======== @@ -17,8 +18,8 @@ application to offer its content in languages and formats tailored to the audience. Django has full support for :doc:`translation of text -</topics/i18n/translation>` and :doc:`formatting of dates, times and numbers -</topics/i18n/formatting>`. +</topics/i18n/translation>`, :doc:`formatting of dates, times and numbers +</topics/i18n/formatting>`, and :doc:`time zones </topics/i18n/timezones>`. Essentially, Django does two things: @@ -27,8 +28,9 @@ Essentially, Django does two things: * It uses these hooks to localize Web apps for particular users according to their preferences. -Obviously, translation depends on the target language. Formatting usually -depends on the target country. +Obviously, translation depends on the target language, and formatting usually +depends on the target country. These informations are provided by browsers in +the ``Accept-Language`` header. However, the time zone isn't readily available. Definitions =========== diff --git a/docs/topics/i18n/timezones.txt b/docs/topics/i18n/timezones.txt new file mode 100644 index 0000000000..41e8380acc --- /dev/null +++ b/docs/topics/i18n/timezones.txt @@ -0,0 +1,429 @@ +.. _time-zones: + +========== +Time zones +========== + +.. versionadded:: 1.4 + +Overview +======== + +When support for time zones is enabled, Django stores date and time +information in UTC in the database, uses time zone-aware datetime objects +internally, and translates them to the end user's time zone in templates and +forms. + +This is handy if your users live in more than one time zone and you want to +display date and time information according to each user's wall clock. Even if +your website is available in only one time zone, it's still a good practice to +store data in UTC in your database. Here is why. + +Many countries have a system of daylight saving time (DST), where clocks are +moved forwards in spring and backwards in autumn. If you're working in local +time, you're likely to encounter errors twice a year, when the transitions +happen. pytz' docs discuss `these issues`_ in greater detail. It probably +doesn't matter for your blog, but it's more annoying if you over-bill or +under-bill your customers by one hour, twice a year, every year. The solution +to this problem is to use UTC in the code and local time only when +interacting with end users. + +Time zone support is disabled by default. To enable it, set :setting:`USE_TZ = +True <USE_TZ>` in your settings file. Installing pytz_ is highly recommended, +but not mandatory. + +.. note:: + + The default :file:`settings.py` file created by :djadmin:`django-admin.py + startproject <startproject>` includes :setting:`USE_TZ = True <USE_TZ>` + for convenience. + +.. note:: + + There is also an independent but related :setting:`USE_L10N` setting that + controls if Django should activate format localization. See + :doc:`/topics/i18n/formatting` for more details. + +Concepts +======== + +Naive and aware datetime objects +-------------------------------- + +Python's :class:`datetime.datetime` objects have a ``tzinfo`` attribute that +can be used to store time zone information, represented as an instance of a +subclass of :class:`datetime.tzinfo`. When this attribute is set and describes +an offset, a datetime object is **aware**; otherwise, it's **naive**. + +You can use :func:`~django.utils.timezone.is_aware` and +:func:`~django.utils.timezone.is_naive` to determine if datetimes are aware or +naive. + +When time zone support is disabled, Django uses naive datetime objects in local +time. This is simple and sufficient for many use cases. In this mode, to obtain +the current time, you would write:: + + import datetime + + now = datetime.datetime.now() + +When time zone support is enabled, Django uses time zone aware datetime +objects. If your code creates datetime objects, they should be aware too. In +this mode, the example above becomes:: + + import datetime + from django.utils.timezone import utc + + now = datetime.datetime.utcnow().replace(tzinfo=utc) + +.. note:: + + :mod:`django.utils.timezone` provides a + :func:`~django.utils.timezone.now()` function that returns a naive or + aware datetime object according to the value of :setting:`USE_TZ`. + +.. warning:: + + Dealing with aware datetime objects isn't always intuitive. For instance, + the ``tzinfo`` argument of the standard datetime constructor doesn't work + reliably for time zones with DST. Using UTC is generally safe; if you're + using other time zones, you should review `pytz' documentation <pytz>`_ + carefully. + +.. note:: + + Python's :class:`datetime.time` objects also feature a ``tzinfo`` + attribute, and PostgreSQL has a matching ``time with time zone`` type. + However, as PostgreSQL's docs put it, this type "exhibits properties which + lead to questionable usefulness". + + Django only supports naive time objects and will raise an exception if you + attempt to save an aware time object. + +.. _naive-datetime-objects: + +Interpretation of naive datetime objects +---------------------------------------- + +When :setting:`USE_TZ` is ``True``, Django still accepts naive datetime +objects, in order to preserve backwards-compatibility. It attempts to make them +aware by interpreting them in the :ref:`default time zone +<default-current-time-zone>`. + +Unfortunately, during DST transitions, some datetimes don't exist or are +ambiguous. In such situations, pytz_ raises an exception. Other +:class:`~datetime.tzinfo` implementations, such as the local time zone used as +a fallback when pytz_ isn't installed, may raise an exception or return +inaccurate results. That's why you should always create aware datetime objects +when time zone support is enabled. + +In practice, this is rarely an issue. Django gives you aware datetime objects +in the models and forms, and most often, new datetime objects are created from +existing ones through :class:`~datetime.timedelta` arithmetic. The only +datetime that's often created in application code is the current time, and +:func:`timezone.now() <django.utils.timezone.now>` automatically does the +right thing. + +.. _default-current-time-zone: + +Default time zone and current time zone +--------------------------------------- + +The **default time zone** is the time zone defined by the :setting:`TIME_ZONE` +setting. + +When pytz_ is available, Django loads the definition of the default time zone +from the `tz database`_. This is the most accurate solution. Otherwise, it +relies on the difference between local time and UTC, as reported by the +operating system, to compute conversions. This is less reliable, especially +around DST transitions. + +The **current time zone** is the time zone that's used for rendering. + +You should set it to the end user's actual time zone with +:func:`~django.utils.timezone.activate`. Otherwise, the default time zone is +used. + +.. note:: + + As explained in the documentation of :setting:`TIME_ZONE`, Django sets + environment variables so that its process runs in the default time zone. + This happens regardless of the value of :setting:`USE_TZ` and of the + current time zone. + + When :setting:`USE_TZ` is ``True``, this is useful to preserve + backwards-compatibility with applications that still rely on local time. + However, :ref:`as explained above <naive-datetime-objects>`, this isn't + entirely reliable, and you should always work with aware datetimes in UTC + in your own code. For instance, use + :meth:`~datetime.datetime.utcfromtimestamp` instead of + :meth:`~datetime.datetime.fromtimestamp` -- and don't forget to set + ``tzinfo`` to :data:`~django.utils.timezone.utc`. + +Selecting the current time zone +------------------------------- + +The current time zone is the equivalent of the current :term:`locale <locale +name>` for translations. However, there's no equivalent of the +``Accept-Language`` HTTP header that Django could use to determine the user's +time zone automatically. Instead, Django provides :ref:`time zone selection +functions <time-zone-selection-functions>`. Use them to build the time zone +selection logic that makes sense for you. + +Most websites who care about time zones just ask users in which time zone they +live and store this information in the user's profile. For anonymous users, +they use the time zone of their primary audience or UTC. pytz_ provides +helpers, like a list of time zones per country, that you can use to pre-select +the most likely choices. + +Here's an example that stores the current timezone in the session. (It skips +error handling entirely for the sake of simplicity.) + +Add the following middleware to :setting:`MIDDLEWARE_CLASSES`:: + + from django.utils import timezone + + class TimezoneMiddleware(object): + def process_request(self, request): + tz = request.session.get('django_timezone') + if tz: + timezone.activate(tz) + +Create a view that can set the current timezone:: + + import pytz + from django.shortcuts import redirect, render + + def set_timezone(request): + if request.method == 'POST': + request.session[session_key] = pytz.timezone(request.POST['timezone']) + return redirect('/') + else: + return render(request, 'template.html', {'timezones': pytz.common_timezones}) + +Include in :file:`template.html` a form that will ``POST`` to this view: + +.. code-block:: html+django + + {% load tz %}{% load url from future %} + <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> + +Time zone aware input in forms +============================== + +When you enable time zone support, Django interprets datetimes entered in +forms in the :ref:`current time zone <default-current-time-zone>` and returns +aware datetime objects in ``cleaned_data``. + +If the current time zone raises an exception for datetimes that don't exist or +are ambiguous because they fall in a DST transition (the timezones provided by +pytz_ do this), such datetimes will be reported as invalid values. + +.. _time-zones-in-templates: + +Time zone aware output in templates +=================================== + +When you enable time zone support, Django converts aware datetime objects to +the :ref:`current time zone <default-current-time-zone>` when they're rendered +in templates. This behaves very much like :doc:`format localization +</topics/i18n/formatting>`. + +.. warning:: + + Django doesn't convert naive datetime objects, because they could be + ambiguous, and because your code should never produce naive datetimes when + time zone support is enabled. However, you can force conversion with the + template filters described below. + +Conversion to local time isn't always appropriate -- you may be generating +output for computers rather than for humans. The following filters and tags, +provided the ``tz`` template library, allow you to control the time zone +conversions. + +Template tags +------------- + +.. templatetag:: localtime + +localtime +~~~~~~~~~ + +Enables or disables conversion of aware datetime objects to the current time +zone in the contained block. + +This tag has exactly the same effects as the :setting:`USE_TZ` setting as far +as the template engine is concerned. It allows a more fine grained control of +conversion. + +To activate or deactivate conversion for a template block, use:: + + {% load tz %} + + {% localtime on %} + {{ value }} + {% endlocaltime %} + + {% localtime off %} + {{ value }} + {% endlocaltime %} + +.. note:: + + The value of :setting:`USE_TZ` isn't respected inside of a + ``{% localtime %}`` block. + +.. templatetag:: timezone + +timezone +~~~~~~~~ + +Sets or unsets the current time zone in the contained block. When the current +time zone is unset, the default time zone applies. + +:: + + {% load tz %} + + {% timezone "Europe/Paris" %} + Paris time: {{ value }} + {% endtimezone %} + + {% timezone None %} + Server time: {{ value }} + {% endtimezone %} + +.. note:: + + In the second block, ``None`` resolves to the Python object ``None`` + because isn't defined in the template context, not because it's the string + ``None``. + +.. templatetag:: get_current_timezone + +get_current_timezone +~~~~~~~~~~~~~~~~~~~~ + +When the :func:`django.core.context_processors.tz` context processor is +enabled -- by default, it is -- each :class:`~django.template.RequestContext` +contains a ``TIME_ZONE`` variable that provides the name of the current time +zone. + +If you don't use a :class:`~django.template.RequestContext`, you can obtain +this value with the ``get_current_timezone`` tag:: + + {% get_current_timezone as TIME_ZONE %} + +Template filters +---------------- + +These filters accept both aware and naive datetimes. For conversion purposes, +they assume that naive datetimes are in the default time zone. They always +return aware datetimes. + +.. templatefilter:: aslocaltime + +aslocaltime +~~~~~~~~~~~ + +Forces conversion of a single value to the current time zone. + +For example:: + + {% load tz %} + + {{ value|aslocaltime }} + +.. templatefilter:: asutc + +asutc +~~~~~ + +Forces conversion of a single value to UTC. + +For example:: + + {% load tz %} + + {{ value|asutc }} + +astimezone +~~~~~~~~~~ + +Forces conversion of a single value to an arbitrary timezone. + +The argument must be an instance of a :class:`~datetime.tzinfo` subclass or a +time zone name. If it is a time zone name, pytz_ is required. + +For example:: + + {% load tz %} + + {{ value|astimezone:"Europe/Paris" }} + +.. _time-zones-migration-guide: + +Migration guide +=============== + +Here's how to migrate a project that was started before Django supported time +zones. + +Data +---- + +PostgreSQL +~~~~~~~~~~ + +The PostgreSQL backend stores datetimes as ``timestamp with time zone``. In +practice, this means it converts datetimes from the connection's time zone to +UTC on storage, and from UTC to the connection's time zone on retrieval. + +As a consequence, 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 :setting:`TIME_ZONE` or ``UTC`` respectively, so that Django +obtains correct datetimes in all cases. You don't need to perform any data +conversions. + +Other databases +~~~~~~~~~~~~~~~ + +Other backends store datetimes without time zone information. If you switch +from ``USE_TZ = False`` to ``USE_TZ = True``, you must convert your data from +local time to UTC -- which isn't deterministic if your local time has DST. + +Code +---- + +The first step is to add :setting:`USE_TZ = True <USE_TZ>` to your settings +file and install pytz_ (if possible). At this point, things should mostly +work. If you create naive datetime objects in your code, Django makes them +aware when necessary. + +However, these conversions may fail around DST transitions, which means you +aren't getting the full benefits of time zone support yet. Also, you're likely +to run into a few problems because it's impossible to compare a naive datetime +with an aware datetime. Since Django now gives you aware datetimes, you'll get +exceptions wherever you compare a datetime that comes from a model or a form +with a naive datetime that you've created in your code. + +So the second step is to refactor your code wherever you instanciate datetime +objects to make them aware. This can be done incrementally. +:mod:`django.utils.timezone` defines some handy helpers for compatibility +code: :func:`~django.utils.timezone.is_aware`, +:func:`~django.utils.timezone.is_naive`, +:func:`~django.utils.timezone.make_aware`, and +:func:`~django.utils.timezone.make_naive`. + +.. _pytz: http://pytz.sourceforge.net/ +.. _these issues: http://pytz.sourceforge.net/#problems-with-localtime +.. _tz database: http://en.wikipedia.org/wiki/Tz_database |
