single |
# django-timezone-field
[CI]
[codecov]
[pypi downloads]
[pypi python support]
[pypi django support]
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:
- Django <= 3.X: `use_pytz` defaults to `True`
- Django == 4.X: `use_pytz` defaults to the value of
[`django.conf.settings.USE_DEPRECATED_PYTZ`],
which itself defaults to `False`
- Django >= 5.X:
[drops support for `pytz` altogether],
and this app has done the same.
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 DB]
- `zoneinfo` 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
```python
import zoneinfo
import pytz
from django.db import models
from timezone_field import TimeZoneField
class MyModel(models.Model):
tz1 = TimeZoneField(default="Asia/Dubai") # defaults
supported, in ModelForm renders like "Asia/Dubai"
tz2 = TimeZoneField(choices_display="WITH_GMT_OFFSET") # in ModelForm
renders like "GMT+04:00 Asia/Dubai"
tz3 = TimeZoneField(use_pytz=True) # returns pytz
timezone objects
tz4 = TimeZoneField(use_pytz=False) # returns
zoneinfo objects
my_model = MyModel(
tz2="America/Vancouver", # assignment of a string
tz3=pytz.timezone("America/Vancouver"), # assignment of a pytz
timezone
tz4=zoneinfo.ZoneInfo("America/Vancouver"), # assignment of a zoneinfo
)
my_model.full_clean() # validates against pytz.common_timezones by default
my_model.save() # values stored in DB as strings
my_model.tz3 # value returned as pytz timezone:
my_model.tz4 # value returned as zoneinfo:
zoneinfo.ZoneInfo(key='America/Vancouver')
my_model.tz1 = "UTC" # assignment of a string, immediately converted to
timezone object
my_model.tz1 # zoneinfo.ZoneInfo(key='UTC') or pytz.utc, depending
on use_pytz default
my_model.tz2 = "Invalid/Not_A_Zone" # immediately raises ValidationError
```
### Form Field
```python
|