On , I learnt ...

To prefer dateutil over pytz

When constructing datetime.datetime instances, it’s better to use dateutil to provide the tzinfo argument — avoid using pytz.

That is, prefer this:

import datetime
from dateutil import tz

tzinfo = tz.gettz("Europe/London")
datetime.datetime(2021, 10, 30, 12, 0, tzinfo=tzinfo)

to

import datetime
import pytz

tzinfo = pytz.timezone("Europe/London")
datetime.datetime(2021, 10, 30, 12, 0, tzinfo=tzinfo)

Why? Because passing pytz’s timezones to the datetime.datetime constructor can often lead to bugs after date arithmetic (i.e. computing new dates using datetime.timedelta). This is noted in the pytz docs:

pytz docs

It’s easy to be lulled into a false sense of security as such bugs don’t affect timezones without daylight savings transitions, like UTC.

See pytz: The Fastest Footgun in the West for more details.