I do suggest carefully reading the PEP and the discussions, because I believe I’ve covered a lot of this already. The caching behavior here seems complicated when it’s explained in detail, but this complexity is designed to make it so that it does what you would expect by default.
What you seem to be suggesting with this “upgrade” function would be something where you mutate existing time zones at some point. Even if you’re not mutating the object in-memory, this is a non-starter, because it would change equality relationships between existing datetimes, and also break the invariant that if
y are hashable and
x == y, then
hash(x) == hash(y), because time zone offsets are calculated lazily, but they are a component of datetime equality and hash calculations. So, under your scheme:
zi = ZoneInfo("Europe/Italy") dt0 = datetime(2021, 1, 1, tzinfo=zi) dt0_utc = dt0.astimezone(timezone.utc) print(dt0 == dt0_utc) # True hash(dt0) # Hash is cached - the alternative is worse # Italy changes and data is updated, mutating zi dt1 = datetime(2021, 1, 1, tzinfo=ZoneInfo("Europe/Italy")) print(dt0 == dt1) # True print(hash(dt0) == hash(dt1)) # False! print(dt0 == dt0_utc) # False!
This is actually one reason that I will soon need to update the PEP to rule out the possibility of using ICU on Windows - after some investigation it seems that we cannot load all the data into a single object using the ICU headers that Windows exposes, and without that there are some gnarly edge cases that we can run into.
The current system will give people pretty much what they expect. The
.clear_cache() functions exist to enable people with non-standard needs or preferences to make other trade-offs with respect to comparison semantics and freshness of data.