datetime.utcnow() classmethod is harmful and should be replaced with:
from datetime import datetime, timezone datetime.now(timezone.utc)
Naive Time Traveling
utcnow() so dangerous? Although the function gives the correct time in the UTC timezone, the returned
datetime does not include a timezone:
from datetime import datetime now = datetime.utcnow() now.tzinfo is None # True
datetime instances are referred to as naive, and a naive
datetime can have unexpected behavior. For instance, the
timestamp() method of a
datetime instance will assume that any naive
datetime is local time! Although you might not notice this difference on a server set to UTC time, any timestamps will be off by your local time’s UTC offset. Here’s the offset in the
from datetime import datetime datetime.now(timezone.utc).timestamp() - datetime.utcnow().timestamp() # -21600
That puts the
utcnow timestamp 6 hours into the future! If you’re interacting with a service that expects a UTC-based unix timestamp, you’re likely to encounter undefined behavior. Since the naive UTC datetime is assuming that it’s local, timezones with a negative offset will generate timestamps in the future and timezones with positive offsets will be in the past.
The lack of timezone also makes comparing
utcnow() unpredictable. In the
US/Mountain timezone, a
datetime generated after another can report that it was generated before!
from datetime import datetime in_the_past = datetime.utcnow() datetime.now() < in_the_past # True
Although the Python documentation is clear that this function should be avoided, it has yet to be marked as deprecated, even in the upcoming 3.10 release. So double check your code!
By the way, if you want a unix timestamp, I recommend the succinct
import time time.time() # 1623721105.8261912