django-timezone-field
A Django app providing DB, form, and REST framework fields for
zoneinfo
and pytz
timezone
objects.
The transition from pytz
to zoneinfo
Like Django, this app supports both pytz
and zoneinfo
objects while the community transitions away from pytz
to
zoneinfo
. All exposed fields and functions that return a timezone object accept an optional boolean kwarg use_pytz
.
If not explicitly specified, the default value used for use_pytz
matches Django's behavior:
Note that this app does not declare pytz
to be a dependency, so if you're using this app with use_pytz=True
, you'll need
to ensure pytz
is included in the environment yourself.
Differences in recognized timezones between pytz
and zoneinfo
pytz
and zoneinfo
search for timezone data differently.
pytz
bundles and searches within its own copy of the IANA timezone DBzoneinfo
first searches the local system's timezone DB for a match. If no match is found, it then searches within
the tzdata
package if it is installed. The tzdata
package contains a copy of
the IANA timezone DB.
If the local system's timezone DB doesn't cover the entire IANA timezone DB and the tzdata
package is not installed,
you may run across errors like ZoneInfoNotFoundError: 'No time zone found with key Pacific/Kanton'
for seemingly valid
timezones when transitioning from pytz
to zoneinfo
. The easy fix is to add tzdata
to your project with
poetry add tzdata
or pip install tzdata
.
Assuming you have the tzdata
package installed if needed, no
data migration should be necessary when
switching from pytz
to zoneinfo
.
Examples
Database Field
import zoneinfo
import pytz
from django.db import models
from timezone_field import TimeZoneField
class MyModel(models.Model):
tz1 = TimeZoneField(default="Asia/Dubai")
tz2 = TimeZoneField(choices_display="WITH_GMT_OFFSET")
tz3 = TimeZoneField(use_pytz=True)
tz4 = TimeZoneField(use_pytz=False)
my_model = MyModel(
tz2="America/Vancouver",
tz3=pytz.timezone("America/Vancouver"),
tz4=zoneinfo.ZoneInfo("America/Vancouver"),
)
my_model.full_clean()
my_model.save()
my_model.tz3
my_model.tz4
my_model.tz1 = "UTC"
my_model.tz1
my_model.tz2 = "Invalid/Not_A_Zone"
Form Field
from django import forms
from timezone_field import TimeZoneFormField
class MyForm(forms.Form):
tz1 = TimeZoneFormField()
tz2 = TimeZoneFormField(choices_display="WITH_GMT_OFFSET")
tz3 = TimeZoneFormField(use_pytz=True)
tz4 = TimeZoneFormField(use_pytz=False)
my_form = MyForm({"tz3": "Europe/Berlin", "tz4": "Europe/Berlin"})
my_form.full_clean()
my_form.cleaned_data["tz3"]
my_form.cleaned_data["tz4"]
REST Framework Serializer Field
from rest_framework import serializers
from timezone_field.rest_framework import TimeZoneSerializerField
class MySerializer(serializers.Serializer):
tz1 = TimeZoneSerializerField(use_pytz=True)
tz2 = TimeZoneSerializerField(use_pytz=False)
my_serializer = MySerializer(data={
"tz1": "America/Argentina/Buenos_Aires",
"tz2": "America/Argentina/Buenos_Aires",
})
my_serializer.is_valid()
my_serializer.validated_data["tz1"]
my_serializer.validated_data["tz2"]
Installation
Releases are hosted on pypi
and can be installed using various
python packaging tools.
poetry add django-timezone-field
pip install django-timezone-field
Running the tests
From the repository root, with poetry
:
poetry install
poetry run pytest
Changelog
7.0 (2024-07-07)
- Better default sorting of
choices
(#116), (#123) - Convert string value to timezone object immediately on creation/assignment.
Accessing a TimeZoneField will always return a timezone or None (never a string).
(Potentially BREAKING: Unknown timezone names now raise
ValidationError
at time of assignment.
Previously, conversion was delayed until model full_clean
or save
.)
(#57) - Add support for django 5.1
- Drop support for django 3.2, 4.0, 4.1
- Change base class of
TimeZoneSerializerField
from DJRF's Field
to CharField
(#137)
6.1.0 (2023-11-25)
- Add support for django 5.0
- Add support for python 3.12
- Fix issue with
Factory
timezone on some BSD systems (#114)
6.0.1 (2023-09-07)
- Use correct default backend when running with django 3.X (#109)
6.0 (2023-08-20)
- BREAKING:
pytz
removed from dependencies. If you use this package with use_pytz=True
, you'll need to install
pytz
yourself. - Drop support for django 2.2
- Drop support for python 3.7
5.1 (2023-06-18)
- Add django as a dependency of this package, with correct version constraints
(#90)
- Add support for django 4.1, 4.2
- Add support for python 3.11
5.0 (2022-02-08)
- Add support for
zoneinfo
objects (#79) - Add support for django 4.0
- Remove
timezone_field.utils.add_gmt_offset_to_choices
, display_GMT_offset
kwarg (use choices_display
instead) - Drop support for django 3.0, 3.1
- Drop support for python 3.5, 3.6
4.2.3 (2022-01-13)
- Fix sdist installs (#78)
- Officially support python 3.10
4.2.1 (2021-07-07)
- Reinstate
TimeZoneField.default_choices
(#76)
4.2 (2021-07-07)
- Officially support django 3.2, python 3.9
- Fix bug with field deconstruction (#74)
- Housekeeping: use poetry, github actions, pytest
4.1.2 (2021-03-17)
- Avoid
NonExistentTimeError
during DST transition (#70)
4.1.1 (2020-11-28)
- Don't import
rest_framework
from package root (#67)
4.1 (2020-11-28)
- Add Django REST Framework serializer field
- Add new
choices_display
kwarg with supported values WITH_GMT_OFFSET
and STANDARD
- Deprecate
display_GMT_offset
kwarg
4.0 (2019-12-03)
- Add support for django 3.0, python 3.8
- Drop support for django 1.11, 2.0, 2.1, python 2.7, 3.4
3.1 (2019-10-02)
- Officially support django 2.2 (already worked)
- Add option to display TZ offsets in form field (#46)
3.0 (2018-09-15)
- Support django 1.11, 2.0, 2.1
- Add support for python 3.7
- Change default human-readable timezone names to exclude underscores
(#32 &
#37)
2.1 (2018-03-01)
- Add support for django 1.10, 1.11
- Add support for python 3.6
- Add wheel support
- Support bytes in DB fields (#38 &
#39)
2.0 (2016-01-31)
- Drop support for django 1.7, add support for django 1.9
- Drop support for python 3.2, 3.3, add support for python 3.5
- Remove tests from source distribution
1.3 (2015-10-12)
- Drop support for django 1.6, add support for django 1.8
- Various bug fixes
1.2 (2015-02-05)
- For form field, changed default list of accepted timezones from
pytz.all_timezones
to pytz.common_timezones
, to
match DB field behavior.
1.1 (2014-10-05)
- Django 1.7 compatibility
- Added support for formatting
choices
kwarg as [[<str>, <str>], ...]
, in addition to previous format of
[[<pytz.timezone>, <str>], ...]
. - Changed default list of accepted timezones from
pytz.all_timezones
to pytz.common_timezones
. If you have timezones
in your DB that are in pytz.all_timezones
but not in pytz.common_timezones
, this is a backward-incompatible
change. Old behavior can be restored by specifying choices=[(tz, tz) for tz in pytz.all_timezones]
in your model
definition.
1.0 (2013-08-04)
- Initial release as
timezone_field
.
Credits
Originally adapted from Brian Rosner's django-timezones.
Made possible thanks to the work of the
contributors.