Datetime changes in Python 4.0

Tomasz Wesołowski
3 min readApr 1, 2021

--

Have you heard about the upcoming datetime library changes in Python 4? It’s pretty significant because it’s the first notable backward incompatible change in the next major Python version since the whole py2 to py3 transition, and it’s likely to require changes to most of the Python programs during upgrade.

The Persistence of Memory, Salvador Dali

Rationale

The core Python team, given how long it took to deprecate py2, wasn’t exactly happy to do such a transition, and the topic was generally controversial whenever it came up (see this thread for example). Still, they eventually had to agree that the current implementation of datetime does more damage than it's supposed to, and that the design problems with it are fundamental and cannot be fixed in a backwards compatible way without nasty edge cases — all due to the way relativity works and how it doesn't agree with naive interpretation of time.

The PEP quote sums it up best:

Rejected ideas

The idea to publish the corrected datetime package as a separate reldatetime package was initially considered, but after a long debate, it was deemed impractical. The scientific community is a core user group for Python and we should ensure that Python remains a viable option for their use case. It ultimately seems morally wrong to expect this group to switch between two different datetime implementations because of a fundamental architecture error in default implementation. This justifies a backwards incompatible change.

Summary of changes

This code works perfectly now on Python 3.9…

>>> a = datetime(2001, 2, 3, 4, 5, 6, 789, tzinfo=pytz.tzinfo("Europe/Paris"))
>>> b = datetime(2001, 12, 13, 14, 56, 7, tzinfo=pytz.tzinfo("Europe/Warsaw"))
>>> a == b
False
>>> a < b
True

but on Python 4.0, once launched, it will produce the following output:

>>> a = datetime(2001, 2, 3, 4, 5, 6, 789, tzinfo=pytz.tzinfo("Europe/Paris"))
>>> b = datetime(2001, 12, 13, 14, 56, 7, tzinfo=pytz.tzinfo("Europe/Warsaw"))
>>> a == b
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
RelativisticError: 'datetime.datetime' objects cannot be compared without a frame of reference

This reflects the physical fact that two events cannot be considered “simultaneous” unless we consider a particular frame of reference. In fact, depending on the frame of reference you establish, event A can occur before or after event B.

To avoid such ambiguity, the code has to be rewritten to:

>>> with datetime.relativistic.FrameOfReference("Earth"):
... a == b
...
False

The new relativistic module contains the new RelativisticError exception as well as a set of standard frames of reference (including the centre of Earth, the Sun and the Milky Way). Third party libraries similar to pytz will follow to provide additional FrameOfReference implementations to cater for advanced scientific use cases.

That’s the gist, and of course please read the PEP for the rationale and all the interesting implementation details.

2021–04–02 update: This article is parody. I would like to thank all the readers for celebrating April 1st together!

--

--

Tomasz Wesołowski
Tomasz Wesołowski

Written by Tomasz Wesołowski

Have you seen him, he's from the future, he's got a really big computer