Introduction
There are two frequent features in which might be naive datetime objects. The behind some of these objects is that timezones do not matter. Maybe you at all times assume that datetimes are in a set timezone. Or, you’re conscious of timezones and wish to make issues straightforward on your self so at all times assume datetimes are set to UTC.
That is your mistake.
The utcnow() and utctimestamp() features are naive, however different datetime features aren’t.
The Gotcha
>>> from datetime import datetime
>>> dt = datetime.utcfromtimestamp(0)
>>> dt
datetime.datetime(1970, 1, 1, 0, 0)
>>> dt.timestamp()
21600.0
What occurred right here?
This was run on a pc within the Central Normal Time time zone. First, I created an object set to the UNIX epoch – Jan. 1, 1970. Since I utilized utcfromtimestamp() to do that, there is no such thing as a timezone information connected to this object. Once I use the usual timestamp() perform, Python sees there is no such thing as a timestamp to make the most of, so it makes use of the system configured timezone. Therefore the 21,600 second offset from the epoch.
This did not at all times occur although. Someday between Python 2 and Python 3 this habits modified. This assumption that “no timezone means native timezone” launched this gotcha. In my view is not a quite harmful one too.
Resolution
Make the most of specific time stamps in all places. From The Zen of Python – PEP 20:
Express is best than implicit.
>>> import datetime
>>> dt = datetime.datetime.fromtimestamp(0, datetime.UTC)
>>> dt
datetime.datetime(1970, 1, 1, 0, 0, tzinfo=datetime.timezone.utc)
>>> dt.timestamp()
0.0
Discover that by including datetime.UTC to my fromtimestamp() name, I get a datetime object with tzinfo. This makes the conversion from the datetime object again into ta timestamp secure.
That is the best way that Python is shifting. In an effort to appropriate these unsafe assumptions that had been launched early in Python 3, the naive datetime features have been deprecated. In case you had been to run my first block of code in Python 3.12, you obtain a deprecation warning.
>>> dt = datetime.utcfromtimestamp(0)
<stdin>:1: DeprecationWarning: datetime.datetime.utcfromtimestamp() is deprecated and scheduled for elimination in a future model. Use timezone-conscious objects to signify datetimes in UTC: datetime.datetime.fromtimestamp(timestamp, datetime.UTC).
Discover that the message is telling you so as to add the timezone data and to make the most of fromtimestamp(). Within the coming yr – years? – each the generally seen utcnow() amd utcfromtimestamp() can be eliminated.
In my view, as somebody that has fought this bug prior to now, it is a welcome change. Timezone assumptions are troublesome to troubleshoot. Assumptions about underlying habits make it a problem. Operating the identical script in numerous timezones, such as you would with a geographicly numerous crew, makes it even more durable. It is particularly annoying if one in every of your coworkers is using UTC as their time zone in order that the script behaves correctly for them however no others.
I’ve code bases that might want to make this alteration, however in the long run, they are going to be simpler to keep up with the elimination of the utc* features.
