Django 4.0 zoneinfo default timezone implementation

Description

This is the next step in the migration from using pytz to using zoneinfo.

Django 3.2 allowed the use of non-pytz time zones. Django 4.0 makes zoneinfo the default implementation.

Danger

Support for pytz is now deprecated and will be removed in Django 5.0.

settings

Time zone support

In order to follow good practice, the default value of the USE_TZ setting will change from False to True, and time zone support will be enabled by default, in Django 5.0.

# https://docs.djangoproject.com/en/dev/topics/i18n/timezones/
USE_TZ = True
TIME_ZONE_EUROPE_PARIS = "Europe/Paris"
TIME_ZONE = "Europe/Paris"
ZONE_EUROPE_PARIS = ZoneInfo("Europe/Paris")
print(f"{TIME_ZONE=}\n{TIME_ZONE_EUROPE_PARIS=}\n{ZONE_EUROPE_PARIS=}\n")

ZoneInfo Usage

import datetime
from zoneinfo import ZoneInfo
from datetime import timezone
ZONE_LOS_ANGELES = ZoneInfo("America/Los_Angeles")
ZONE_PARIS = ZoneInfo("Europe/Paris")
print(f"{timezone.utc=}")
print(f"{ZONE_LOS_ANGELES=}")
print(f"{ZONE_PARIS=}")
dt_utc = datetime.datetime(2021, 11, 25, 20, tzinfo=timezone.utc)
print(f"{dt_utc=}")
print(f"{dt_utc.astimezone(ZONE_LOS_ANGELES)=}")
print(f"{dt_utc.astimezone(ZONE_PARIS)=}")
print(f"ZONE_LOS_ANGELES: {dt_utc.astimezone(ZONE_LOS_ANGELES):%d/%m/%Y %H:%M}")
print(f"ZONE_PARIS: {dt_utc.astimezone(ZONE_PARIS):%d/%m/%Y %H:%M}")
[14]:     print(f"{timezone.utc=}")
    ...:     print(f"{ZONE_LOS_ANGELES=}")
    ...:     print(f"{ZONE_PARIS=}")
    ...:     dt_utc = datetime.datetime(2021, 11, 25, 20, tzinfo=timezone.utc)
    ...:     print(f"{dt_utc.astimezone(ZONE_LOS_ANGELES)=}")
    ...:     print(f"{dt_utc.astimezone(ZONE_PARIS)=}")
    ...:
timezone.utc=datetime.timezone.utc
ZONE_LOS_ANGELES=zoneinfo.ZoneInfo(key='America/Los_Angeles')
ZONE_PARIS=zoneinfo.ZoneInfo(key='Europe/Paris')
dt_utc.astimezone(ZONE_LOS_ANGELES)=datetime.datetime(2021, 11, 25, 12, 0, tzinfo=zoneinfo.ZoneInfo(key='America/Los_Angeles'))
dt_utc.astimezone(ZONE_PARIS)=datetime.datetime(2021, 11, 25, 21, 0, tzinfo=zoneinfo.ZoneInfo(key='Europe/Paris'))

In [15]:     print(f"{dt_utc=}")
    ...:     print(f"{dt_utc.astimezone(ZONE_LOS_ANGELES)=}")
    ...:     print(f"{dt_utc.astimezone(ZONE_PARIS)=}")
    ...:
dt_utc=datetime.datetime(2021, 11, 25, 20, 0, tzinfo=datetime.timezone.utc)
dt_utc.astimezone(ZONE_LOS_ANGELES)=datetime.datetime(2021, 11, 25, 12, 0, tzinfo=zoneinfo.ZoneInfo(key='America/Los_Angeles'))
dt_utc.astimezone(ZONE_PARIS)=datetime.datetime(2021, 11, 25, 21, 0, tzinfo=zoneinfo.ZoneInfo(key='Europe/Paris'))

Code

def get_datetime_paris_for_daterange(date_source: datetime.datetime) -> str:
    """Exemple: "23/02/2021 8:30
    Utilisé par le composant Javascript daterange

    Voir http://www.daterangepicker.com/#config

    Il faut lui passer l'heure de la zone Paris
    """
    str_datetime_for_daterange = (
        f"{date_source.astimezone(settings.ZONE_EUROPE_PARIS):%d/%m/%Y %H:%M}"
    )

    return str_datetime_for_daterange

Comments

But if any, if there are other issues that come up, and we need to know about them, because zone info is the future of time zones in Python.

So it’s time for us to make this change. And that will be the transitional settings available all through four point x, the four point X series, so till Django 5.0, you can use this, but ideally, you would get you would migrate sooner rather than later and drop using that deprecated party said, and use an empire.