Python etc / datetime.datetime.fold


Daylight saving time (DST) is the practice of advancing clocks (typically by one hour) during warmer months so that darkness falls at a later clock time and then turning it back for colder months. That means, sometimes, once a year the clock shows the same time twice. It can also happen when the UTC shift of the current timezone is decreased.

To distinguish such situations, PEP-495 (landed in Python 3.6) introduce the fold attribute for datetime that is 0 or 1 depending if this is the first or the second pass through the given time in the given timezone.

For example, in Amsterdam the time is shifted from CEST (Central European Summer Time) to CET (Central European Time) on the last Sunday of October:

from datetime import datetime, timedelta, timezone
from zoneinfo import ZoneInfo

ams = ZoneInfo('Europe/Amsterdam')
d0 = datetime(2023, 10, 29, 0, 0, tzinfo=timezone.utc)
for h in range(3):
    du = d0 + timedelta(hours=h)
    dl = du.astimezone(ams)
    m = f'{du.time()} UTC is {dl.time()} {dl.tzname()} (fold={dl.fold})'

This code will print:

00:00:00 UTC is 02:00:00 CEST (fold=0)
01:00:00 UTC is 02:00:00 CET (fold=1)
02:00:00 UTC is 03:00:00 CET (fold=0)

However, you should keep in mind that fold is not considered in comparison operations:

d1 = datetime(2023, 10, 29, 2, 0, tzinfo=ams)
d2 = datetime(2023, 10, 29, 2, 0, fold=1, tzinfo=ams)
d1 == d2  # True

Now imagine that your system has a bug because of not handling this. That happens once a year. On Sunday. At night 🌚