summaryrefslogtreecommitdiff
path: root/docs
diff options
context:
space:
mode:
authorCarlton Gibson <carlton.gibson@noumenal.es>2021-09-09 15:15:44 +0200
committerCarlton Gibson <carlton.gibson@noumenal.es>2021-09-16 12:11:05 +0200
commit306607d5b99b6eca6ae2c1e726d8eb32b9b2ca1b (patch)
tree607d1b06feafaf28fc2e09c70652d30659707537 /docs
parent7132d17de1399345a38858c20221850bdef43d0e (diff)
Fixed #32365 -- Made zoneinfo the default timezone implementation.
Thanks to Adam Johnson, Aymeric Augustin, David Smith, Mariusz Felisiak, Nick Pope, and Paul Ganssle for reviews.
Diffstat (limited to 'docs')
-rw-r--r--docs/internals/deprecation.txt18
-rw-r--r--docs/ref/models/database-functions.txt57
-rw-r--r--docs/ref/models/querysets.txt8
-rw-r--r--docs/ref/settings.txt25
-rw-r--r--docs/ref/utils.txt38
-rw-r--r--docs/releases/4.0.txt66
-rw-r--r--docs/topics/i18n/timezones.txt108
7 files changed, 224 insertions, 96 deletions
diff --git a/docs/internals/deprecation.txt b/docs/internals/deprecation.txt
index 6154fefa3b..09be9e66e4 100644
--- a/docs/internals/deprecation.txt
+++ b/docs/internals/deprecation.txt
@@ -36,6 +36,24 @@ details on these changes.
* The ``USE_L10N`` setting will be removed.
+* The ``USE_DEPRECATED_PYTZ`` transitional setting will be removed.
+
+* Support for ``pytz`` timezones will be removed.
+
+* The ``is_dst`` argument will be removed from:
+
+ * ``QuerySet.datetimes()``
+ * ``django.utils.timezone.make_aware()``
+ * ``django.db.models.functions.Trunc()``
+ * ``django.db.models.functions.TruncSecond()``
+ * ``django.db.models.functions.TruncMinute()``
+ * ``django.db.models.functions.TruncHour()``
+ * ``django.db.models.functions.TruncDay()``
+ * ``django.db.models.functions.TruncWeek()``
+ * ``django.db.models.functions.TruncMonth()``
+ * ``django.db.models.functions.TruncQuarter()``
+ * ``django.db.models.functions.TruncYear()``
+
.. _deprecation-removed-in-4.1:
4.1
diff --git a/docs/ref/models/database-functions.txt b/docs/ref/models/database-functions.txt
index 18dfdae976..3d2e436b67 100644
--- a/docs/ref/models/database-functions.txt
+++ b/docs/ref/models/database-functions.txt
@@ -242,7 +242,8 @@ Takes an ``expression`` representing a ``DateField``, ``DateTimeField``,
of the date referenced by ``lookup_name`` as an ``IntegerField``.
Django usually uses the databases' extract function, so you may use any
``lookup_name`` that your database supports. A ``tzinfo`` subclass, usually
-provided by ``pytz``, can be passed to extract a value in a specific timezone.
+provided by :mod:`zoneinfo`, can be passed to extract a value in a specific
+timezone.
Given the datetime ``2015-06-15 23:30:01.000321+00:00``, the built-in
``lookup_name``\s return:
@@ -450,8 +451,8 @@ to that timezone before the value is extracted. The example below converts to
the Melbourne timezone (UTC +10:00), which changes the day, weekday, and hour
values that are returned::
- >>> import pytz
- >>> melb = pytz.timezone('Australia/Melbourne') # UTC+10:00
+ >>> import zoneinfo
+ >>> melb = zoneinfo.ZoneInfo('Australia/Melbourne') # UTC+10:00
>>> with timezone.override(melb):
... Experiment.objects.annotate(
... day=ExtractDay('start_datetime'),
@@ -466,8 +467,8 @@ values that are returned::
Explicitly passing the timezone to the ``Extract`` function behaves in the same
way, and takes priority over an active timezone::
- >>> import pytz
- >>> melb = pytz.timezone('Australia/Melbourne')
+ >>> import zoneinfo
+ >>> melb = zoneinfo.ZoneInfo('Australia/Melbourne')
>>> Experiment.objects.annotate(
... day=ExtractDay('start_datetime', tzinfo=melb),
... weekday=ExtractWeekDay('start_datetime', tzinfo=melb),
@@ -517,12 +518,16 @@ part, and an ``output_field`` that's either ``DateTimeField()``,
``TimeField()``, or ``DateField()``. It returns a datetime, date, or time
depending on ``output_field``, with fields up to ``kind`` set to their minimum
value. If ``output_field`` is omitted, it will default to the ``output_field``
-of ``expression``. A ``tzinfo`` subclass, usually provided by ``pytz``, can be
-passed to truncate a value in a specific timezone.
+of ``expression``. A ``tzinfo`` subclass, usually provided by :mod:`zoneinfo`,
+can be passed to truncate a value in a specific timezone.
-The ``is_dst`` parameter indicates whether or not ``pytz`` should interpret
-nonexistent and ambiguous datetimes in daylight saving time. By default (when
-``is_dst=None``), ``pytz`` raises an exception for such datetimes.
+.. deprecated:: 4.0
+
+ The ``is_dst`` parameter indicates whether or not ``pytz`` should interpret
+ nonexistent and ambiguous datetimes in daylight saving time. By default
+ (when ``is_dst=None``), ``pytz`` raises an exception for such datetimes.
+
+ The ``is_dst`` parameter is deprecated and will be removed in Django 5.0.
Given the datetime ``2015-06-15 14:30:50.000321+00:00``, the built-in ``kind``\s
return:
@@ -607,6 +612,10 @@ Usage example::
.. attribute:: kind = 'quarter'
+.. deprecated:: 4.0
+
+ The ``is_dst`` parameter is deprecated and will be removed in Django 5.0.
+
These are logically equivalent to ``Trunc('date_field', kind)``. They truncate
all parts of the date up to ``kind`` which allows grouping or filtering dates
with less precision. ``expression`` can have an ``output_field`` of either
@@ -634,8 +643,8 @@ that deal with date-parts can be used with ``DateField``::
2014-01-01 1
2015-01-01 2
- >>> import pytz
- >>> melb = pytz.timezone('Australia/Melbourne')
+ >>> import zoneinfo
+ >>> melb = zoneinfo.ZoneInfo('Australia/Melbourne')
>>> experiments_per_month = Experiment.objects.annotate(
... month=TruncMonth('start_datetime', tzinfo=melb)).values('month').annotate(
... experiments=Count('id'))
@@ -691,6 +700,10 @@ truncate function. It's also registered as a transform on ``DateTimeField`` as
.. attribute:: kind = 'second'
+.. deprecated:: 4.0
+
+ The ``is_dst`` parameter is deprecated and will be removed in Django 5.0.
+
These are logically equivalent to ``Trunc('datetime_field', kind)``. They
truncate all parts of the date up to ``kind`` and allow grouping or filtering
datetimes with less precision. ``expression`` must have an ``output_field`` of
@@ -704,10 +717,10 @@ Usage example::
... TruncDate, TruncDay, TruncHour, TruncMinute, TruncSecond,
... )
>>> from django.utils import timezone
- >>> import pytz
+ >>> import zoneinfo
>>> start1 = datetime(2014, 6, 15, 14, 30, 50, 321, tzinfo=timezone.utc)
>>> Experiment.objects.create(start_datetime=start1, start_date=start1.date())
- >>> melb = pytz.timezone('Australia/Melbourne')
+ >>> melb = zoneinfo.ZoneInfo('Australia/Melbourne')
>>> Experiment.objects.annotate(
... date=TruncDate('start_datetime'),
... day=TruncDay('start_datetime', tzinfo=melb),
@@ -716,10 +729,10 @@ Usage example::
... second=TruncSecond('start_datetime'),
... ).values('date', 'day', 'hour', 'minute', 'second').get()
{'date': datetime.date(2014, 6, 15),
- 'day': datetime.datetime(2014, 6, 16, 0, 0, tzinfo=<DstTzInfo 'Australia/Melbourne' AEST+10:00:00 STD>),
- 'hour': datetime.datetime(2014, 6, 16, 0, 0, tzinfo=<DstTzInfo 'Australia/Melbourne' AEST+10:00:00 STD>),
- 'minute': 'minute': datetime.datetime(2014, 6, 15, 14, 30, tzinfo=<UTC>),
- 'second': datetime.datetime(2014, 6, 15, 14, 30, 50, tzinfo=<UTC>)
+ 'day': datetime.datetime(2014, 6, 16, 0, 0, tzinfo=zoneinfo.ZoneInfo('Australia/Melbourne')),
+ 'hour': datetime.datetime(2014, 6, 16, 0, 0, tzinfo=zoneinfo.ZoneInfo('Australia/Melbourne')),
+ 'minute': 'minute': datetime.datetime(2014, 6, 15, 14, 30, tzinfo=zoneinfo.ZoneInfo('UTC')),
+ 'second': datetime.datetime(2014, 6, 15, 14, 30, 50, tzinfo=zoneinfo.ZoneInfo('UTC'))
}
``TimeField`` truncation
@@ -740,6 +753,10 @@ Usage example::
.. attribute:: kind = 'second'
+.. deprecated:: 4.0
+
+ The ``is_dst`` parameter is deprecated and will be removed in Django 5.0.
+
These are logically equivalent to ``Trunc('time_field', kind)``. They truncate
all parts of the time up to ``kind`` which allows grouping or filtering times
with less precision. ``expression`` can have an ``output_field`` of either
@@ -767,8 +784,8 @@ that deal with time-parts can be used with ``TimeField``::
14:00:00 2
17:00:00 1
- >>> import pytz
- >>> melb = pytz.timezone('Australia/Melbourne')
+ >>> import zoneinfo
+ >>> melb = zoneinfo.ZoneInfo('Australia/Melbourne')
>>> experiments_per_hour = Experiment.objects.annotate(
... hour=TruncHour('start_datetime', tzinfo=melb),
... ).values('hour').annotate(experiments=Count('id'))
diff --git a/docs/ref/models/querysets.txt b/docs/ref/models/querysets.txt
index 583d313b5b..6a4ec0fb05 100644
--- a/docs/ref/models/querysets.txt
+++ b/docs/ref/models/querysets.txt
@@ -834,6 +834,10 @@ object. If it's ``None``, Django uses the :ref:`current time zone
ambiguous datetimes in daylight saving time. By default (when ``is_dst=None``),
``pytz`` raises an exception for such datetimes.
+.. deprecated:: 4.0
+
+ The ``is_dst`` parameter is deprecated and will be removed in Django 5.0.
+
.. _database-time-zone-definitions:
.. note::
@@ -842,13 +846,11 @@ ambiguous datetimes in daylight saving time. By default (when ``is_dst=None``),
As a consequence, your database must be able to interpret the value of
``tzinfo.tzname(None)``. This translates into the following requirements:
- - SQLite: no requirements. Conversions are performed in Python with pytz_
- (installed when you install Django).
+ - SQLite: no requirements. Conversions are performed in Python.
- PostgreSQL: no requirements (see `Time Zones`_).
- Oracle: no requirements (see `Choosing a Time Zone File`_).
- MySQL: load the time zone tables with `mysql_tzinfo_to_sql`_.
- .. _pytz: http://pytz.sourceforge.net/
.. _Time Zones: https://www.postgresql.org/docs/current/datatype-datetime.html#DATATYPE-TIMEZONES
.. _Choosing a Time Zone File: https://docs.oracle.com/en/database/oracle/
oracle-database/18/nlspg/datetime-data-types-and-time-zone-support.html
diff --git a/docs/ref/settings.txt b/docs/ref/settings.txt
index 0639c423bb..f534b8746c 100644
--- a/docs/ref/settings.txt
+++ b/docs/ref/settings.txt
@@ -677,8 +677,8 @@ When :setting:`USE_TZ` is ``False``, it is an error to set this option.
otherwise, you should leave this option unset. It's best to store datetimes
in UTC because it avoids ambiguous or nonexistent datetimes during daylight
saving time changes. Also, receiving datetimes in UTC keeps datetime
- arithmetic simple — there's no need for the ``normalize()`` method provided
- by pytz.
+ arithmetic simple — there's no need to consider potential offset changes
+ over a DST transition.
* If you're connecting to a third-party database that stores datetimes in a
local time rather than UTC, then you must set this option to the
@@ -695,8 +695,8 @@ When :setting:`USE_TZ` is ``False``, it is an error to set this option.
as ``date_trunc``, because their results depend on the time zone.
However, this has a downside: receiving all datetimes in local time makes
- datetime arithmetic more tricky — you must call the ``normalize()`` method
- provided by pytz after each operation.
+ datetime arithmetic more tricky — you must account for possible offset
+ changes over DST transitions.
Consider converting to local time explicitly with ``AT TIME ZONE`` in raw SQL
queries instead of setting the ``TIME_ZONE`` option.
@@ -2758,6 +2758,23 @@ the correct environment.
.. _list of time zones: https://en.wikipedia.org/wiki/List_of_tz_database_time_zones
+.. setting:: USE_DEPRECATED_PYTZ
+
+``USE_DEPRECATED_PYTZ``
+-----------------------
+
+.. versionadded:: 4.0
+
+Default: ``False``
+
+A boolean that specifies whether to use ``pytz``, rather than :mod:`zoneinfo`,
+as the default time zone implementation.
+
+.. deprecated:: 4.0
+
+ This transitional setting is deprecated. Support for using ``pytz`` will be
+ removed in Django 5.0.
+
.. setting:: USE_I18N
``USE_I18N``
diff --git a/docs/ref/utils.txt b/docs/ref/utils.txt
index 3a7f58c5f7..d316c8a8bf 100644
--- a/docs/ref/utils.txt
+++ b/docs/ref/utils.txt
@@ -941,24 +941,30 @@ appropriate entities.
:class:`~datetime.datetime`. If ``timezone`` is set to ``None``, it
defaults to the :ref:`current time zone <default-current-time-zone>`.
- When using ``pytz``, the ``pytz.AmbiguousTimeError`` exception is raised if
- you try to make ``value`` aware during a DST transition where the same time
- occurs twice (when reverting from DST). Setting ``is_dst`` to ``True`` or
- ``False`` will avoid the exception by choosing if the time is
- pre-transition or post-transition respectively.
+ .. deprecated:: 4.0
- When using ``pytz``, the ``pytz.NonExistentTimeError`` exception is raised
- if you try to make ``value`` aware during a DST transition such that the
- time never occurred. For example, if the 2:00 hour is skipped during a DST
- transition, trying to make 2:30 aware in that time zone will raise an
- exception. To avoid that you can use ``is_dst`` to specify how
- ``make_aware()`` should interpret such a nonexistent time. If
- ``is_dst=True`` then the above time would be interpreted as 2:30 DST time
- (equivalent to 1:30 local time). Conversely, if ``is_dst=False`` the time
- would be interpreted as 2:30 standard time (equivalent to 3:30 local time).
+ When using ``pytz``, the ``pytz.AmbiguousTimeError`` exception is
+ raised if you try to make ``value`` aware during a DST transition where
+ the same time occurs twice (when reverting from DST). Setting
+ ``is_dst`` to ``True`` or ``False`` will avoid the exception by
+ choosing if the time is pre-transition or post-transition respectively.
- The ``is_dst`` parameter has no effect when using non-``pytz`` timezone
- implementations.
+ When using ``pytz``, the ``pytz.NonExistentTimeError`` exception is
+ raised if you try to make ``value`` aware during a DST transition such
+ that the time never occurred. For example, if the 2:00 hour is skipped
+ during a DST transition, trying to make 2:30 aware in that time zone
+ will raise an exception. To avoid that you can use ``is_dst`` to
+ specify how ``make_aware()`` should interpret such a nonexistent time.
+ If ``is_dst=True`` then the above time would be interpreted as 2:30 DST
+ time (equivalent to 1:30 local time). Conversely, if ``is_dst=False``
+ the time would be interpreted as 2:30 standard time (equivalent to 3:30
+ local time).
+
+ The ``is_dst`` parameter has no effect when using non-``pytz`` timezone
+ implementations.
+
+ The ``is_dst`` parameter is deprecated and will be removed in Django
+ 5.0.
.. function:: make_naive(value, timezone=None)
diff --git a/docs/releases/4.0.txt b/docs/releases/4.0.txt
index 540500af47..af168a6d33 100644
--- a/docs/releases/4.0.txt
+++ b/docs/releases/4.0.txt
@@ -28,6 +28,46 @@ The Django 3.2.x series is the last to support Python 3.6 and 3.7.
What's new in Django 4.0
========================
+``zoneinfo`` default timezone implementation
+--------------------------------------------
+
+The Python standard library's :mod:`zoneinfo` is now the default timezone
+implementation in Django.
+
+This is the next step in the migration from using ``pytz`` to using
+:mod:`zoneinfo`. Django 3.2 allowed the use of non-``pytz`` time zones. Django
+4.0 makes ``zoneinfo`` the default implementation. Support for ``pytz`` is now
+deprecated and will be removed in Django 5.0.
+
+:mod:`zoneinfo` is part of the Python standard library from Python 3.9. The
+``backports.zoneinfo`` package is automatically installed alongside Django if
+you are using Python 3.8.
+
+The move to ``zoneinfo`` should be largely transparent. Selection of the
+current timezone, conversion of datetime instances to the current timezone in
+forms and templates, as well as operations on aware datetimes in UTC are
+unaffected.
+
+However, if you are you are working with non-UTC time zones, and using the
+``pytz`` ``normalize()`` and ``localize()`` APIs, possibly with the
+:setting:`DATABASE-TIME_ZONE` setting, you will need to audit your code, since
+``pytz`` and ``zoneinfo`` are not entirely equivalent.
+
+To give time for such an audit, the transitional :setting:`USE_DEPRECATED_PYTZ`
+setting allows continued use of ``pytz`` during the 4.x release cycle. This
+setting will be removed in Django 5.0.
+
+In addition, a `pytz_deprecation_shim`_ package, created by the ``zoneinfo``
+author, can be used to assist with the migration from ``pytz``. This package
+provides shims to help you safely remove ``pytz``, and has a detailed
+`migration guide`_ showing how to move to the new ``zoneinfo`` APIs.
+
+Using `pytz_deprecation_shim`_ and the :setting:`USE_DEPRECATED_PYTZ`
+transitional setting is recommended if you need a gradual update path.
+
+.. _pytz_deprecation_shim: https://pytz-deprecation-shim.readthedocs.io/en/latest/index.html
+.. _migration guide: https://pytz-deprecation-shim.readthedocs.io/en/latest/migration.html
+
Functional unique constraints
-----------------------------
@@ -595,11 +635,37 @@ Miscellaneous
* The default value of the ``USE_L10N`` setting is changed to ``True``. See the
:ref:`Localization section <use_l10n_deprecation>` above for more details.
+* As part of the :ref:`move to zoneinfo <whats-new-4.0>`,
+ :attr:`django.utils.timezone.utc` is changed to alias
+ :attr:`datetime.timezone.utc`.
+
.. _deprecated-features-4.0:
Features deprecated in 4.0
==========================
+Use of ``pytz`` time zones
+--------------------------
+
+As part of the :ref:`move to zoneinfo <whats-new-4.0>`, use of ``pytz`` time
+zones is deprecated.
+
+Accordingly, the ``is_dst`` arguments to the following are also deprecated:
+
+* :meth:`django.db.models.query.QuerySet.datetimes()`
+* :func:`django.db.models.functions.Trunc()`
+* :func:`django.db.models.functions.TruncSecond()`
+* :func:`django.db.models.functions.TruncMinute()`
+* :func:`django.db.models.functions.TruncHour()`
+* :func:`django.db.models.functions.TruncDay()`
+* :func:`django.db.models.functions.TruncWeek()`
+* :func:`django.db.models.functions.TruncMonth()`
+* :func:`django.db.models.functions.TruncQuarter()`
+* :func:`django.db.models.functions.TruncYear()`
+* :func:`django.utils.timezone.make_aware()`
+
+Support for use of ``pytz`` will be removed in Django 5.0.
+
Time zone support
-----------------
diff --git a/docs/topics/i18n/timezones.txt b/docs/topics/i18n/timezones.txt
index 5b475bd44f..6eda217f56 100644
--- a/docs/topics/i18n/timezones.txt
+++ b/docs/topics/i18n/timezones.txt
@@ -19,10 +19,9 @@ practice to store data in UTC in your database. The main reason is daylight
saving time (DST). Many countries have a system of DST, where clocks are moved
forward in spring and backward in autumn. If you're working in local time,
you're likely to encounter errors twice a year, when the transitions happen.
-(The pytz_ documentation discusses `these issues`_ in greater detail.) This
-probably doesn't matter for your blog, but it's a problem 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 use local time only when
+This probably doesn't matter for your blog, but it's a problem 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 use local time only when
interacting with end users.
Time zone support is disabled by default. To enable it, set :setting:`USE_TZ =
@@ -32,15 +31,20 @@ True <USE_TZ>` in your settings file.
In Django 5.0, time zone support will be enabled by default.
-By default, time zone support uses pytz_, which is installed when you install
-Django; Django also supports the use of other time zone implementations like
-:mod:`zoneinfo` by passing :class:`~datetime.tzinfo` objects directly to
-functions in :mod:`django.utils.timezone`.
+Time zone support uses :mod:`zoneinfo`, which is part of the Python standard
+library from Python 3.9. The ``backports.zoneinfo`` package is automatically
+installed alongside Django if you are using Python 3.8.
.. versionchanged:: 3.2
Support for non-``pytz`` timezone implementations was added.
+.. versionchanged:: 4.0
+
+ :mod:`zoneinfo` was made the default timezone implementation. You may
+ continue to use `pytz`_ during the 4.x release cycle via the
+ :setting:`USE_DEPRECATED_PYTZ` setting.
+
.. note::
The default :file:`settings.py` file created by :djadmin:`django-admin
@@ -88,8 +92,8 @@ should be aware too. In this mode, the example above becomes::
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 the `pytz`_ documentation
- carefully.
+ using other time zones, you should review the :mod:`zoneinfo`
+ documentation carefully.
.. note::
@@ -113,8 +117,10 @@ receives one, it attempts to make it aware by interpreting it in the
:ref:`default time zone <default-current-time-zone>` and raises a warning.
Unfortunately, during DST transitions, some datetimes don't exist or are
-ambiguous. In such situations, pytz_ raises an exception. That's why you should
-always create aware datetime objects when time zone support is enabled.
+ambiguous. That's why you should always create aware datetime objects when time
+zone support is enabled. (See the :mod:`Using ZoneInfo section of the zoneinfo
+docs <zoneinfo>` for examples using the ``fold`` attribute to specify the
+offset that should apply to a datetime during a DST transition.)
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
@@ -163,16 +169,16 @@ selection logic that makes sense for you.
Most websites that care about time zones 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.
+the time zone of their primary audience or UTC.
+:func:`zoneinfo.available_timezones` provides a set of available timezones that
+you can use to build a map from likely locations to time zones.
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`::
- import pytz
+ import zoneinfo
from django.utils import timezone
@@ -183,7 +189,7 @@ Add the following middleware to :setting:`MIDDLEWARE`::
def __call__(self, request):
tzname = request.session.get('django_timezone')
if tzname:
- timezone.activate(pytz.timezone(tzname))
+ timezone.activate(zoneinfo.ZoneInfo(tzname))
else:
timezone.deactivate()
return self.get_response(request)
@@ -192,12 +198,19 @@ Create a view that can set the current timezone::
from django.shortcuts import redirect, render
+ # Prepare a map of common locations to timezone choices you wish to offer.
+ common_timezones = {
+ 'London': 'Europe/London',
+ 'Paris': 'Europe/Paris',
+ 'New York': 'America/New_York',
+ }
+
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})
+ return render(request, 'template.html', {'timezones': common_timezones})
Include a form in ``template.html`` that will ``POST`` to this view:
@@ -209,8 +222,8 @@ Include a form in ``template.html`` that will ``POST`` to this view:
{% csrf_token %}
<label for="timezone">Time zone:</label>
<select name="timezone">
- {% for tz in timezones %}
- <option value="{{ tz }}"{% if tz == TIME_ZONE %} selected{% endif %}>{{ tz }}</option>
+ {% for city, tz in timezones %}
+ <option value="{{ tz }}"{% if tz == TIME_ZONE %} selected{% endif %}>{{ city }}</option>
{% endfor %}
</select>
<input type="submit" value="Set">
@@ -225,9 +238,8 @@ 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.
+Converted datetimes that don't exist or are ambiguous because they fall in a
+DST transition will be reported as invalid values.
.. _time-zones-in-templates:
@@ -583,20 +595,20 @@ Troubleshooting
None of this is true in a time zone aware environment::
>>> 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))
+ >>> import zoneinfo
+ >>> paris_tz = zoneinfo.ZoneInfo("Europe/Paris")
+ >>> new_york_tz = zoneinfo.ZoneInfo("America/New_York")
+ >>> paris = datetime.datetime(2012, 3, 3, 1, 30, tzinfo=paris_tz)
+ # This is the correct way to convert between time zones.
+ >>> new_york = 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>)
+ datetime.datetime(2012, 3, 3, 1, 30, tzinfo=zoneinfo.ZoneInfo(key='Europe/Paris'))
>>> new_york
- datetime.datetime(2012, 3, 2, 19, 30, tzinfo=<DstTzInfo 'America/New_York' EST-1 day, 19:00:00 STD>)
+ datetime.datetime(2012, 3, 2, 19, 30, tzinfo=zoneinfo.ZoneInfo(key='America/New_York'))
As this example shows, the same datetime has a different date, depending on
the time zone in which it is represented. But the real problem is more
@@ -621,14 +633,13 @@ Troubleshooting
will be the current timezone::
>>> from django.utils import timezone
- >>> timezone.activate(pytz.timezone("Asia/Singapore"))
+ >>> timezone.activate(zoneinfo.ZoneInfo("Asia/Singapore"))
# For this example, we 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 = paris.astimezone(current_tz)
>>> local
- datetime.datetime(2012, 3, 3, 8, 30, tzinfo=<DstTzInfo 'Asia/Singapore' SGT+8:00:00 STD>)
+ datetime.datetime(2012, 3, 3, 8, 30, tzinfo=zoneinfo.ZoneInfo(key='Asia/Singapore'))
>>> local.date()
datetime.date(2012, 3, 3)
@@ -645,18 +656,14 @@ Usage
``"Europe/Helsinki"`` **time zone. How do I turn that into an aware
datetime?**
- This is exactly what pytz_ is for.
+ Here you need to create the required ``ZoneInfo`` instance and attach it to
+ the naïve datetime::
+ >>> import zoneinfo
>>> 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>)
-
- Note that ``localize`` is a pytz extension to the :class:`~datetime.tzinfo`
- API. Also, you may want to catch ``pytz.InvalidTimeError``. The
- documentation of pytz contains `more examples`_. You should review it
- before attempting to manipulate aware datetimes.
+ >>> naive.replace(tzinfo=zoneinfo.ZoneInfo("Europe/Helsinki"))
+ datetime.datetime(2012, 2, 21, 10, 28, 45, tzinfo=zoneinfo.ZoneInfo(key='Europe/Helsinki'))
#. **How can I obtain the local time in the current time zone?**
@@ -677,19 +684,14 @@ Usage
>>> 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>)
+ datetime.datetime(2012, 3, 3, 20, 10, 53, 873365, tzinfo=zoneinfo.ZoneInfo(key='Europe/Paris'))
In this example, the current time zone is ``"Europe/Paris"``.
#. **How can I see all available time zones?**
- pytz_ provides helpers_, including a list of current time zones and a list
- of all available time zones -- some of which are only of historical
- interest. :mod:`zoneinfo` also provides similar functionality via
- :func:`zoneinfo.available_timezones`.
+ :func:`zoneinfo.available_timezones` provides the set of all valid keys for
+ IANA time zones available to your system. See the docs for usage
+ considerations.
.. _pytz: http://pytz.sourceforge.net/
-.. _more examples: http://pytz.sourceforge.net/#example-usage
-.. _these issues: http://pytz.sourceforge.net/#problems-with-localtime
-.. _helpers: http://pytz.sourceforge.net/#helpers
-.. _tz database: https://en.wikipedia.org/wiki/Tz_database