Why the difference between datetime.now(datetime.timezone.utc) and datetime.datetime.utcnow()

Viewed 732

If you call datetime.datetime.now(datetime.timezone.utc) you get something like datetime.datetime(2021, 9, 8, 1, 33, 19, 684253, tzinfo=datetime.timezone.utc).

If you call datetime.datetime.utcnow(), you get something like datetime.datetime(2021, 9, 8, 1, 33, 20, 283212).

The results seem the equivalent, but they aren't, because the timestamps will differ. Eg. calling datetime.datetime.now(datetime.timezone.utc).timestamp() - datetime.datetime.utcnow().timestamp() returns (for me): -18000.000012159348.

Why is that?

import datetime

print()
print(datetime.datetime.now(datetime.timezone.utc))
print(datetime.datetime.utcnow())

print()
print(datetime.datetime.now(datetime.timezone.utc).timestamp())
print(datetime.datetime.utcnow().timestamp())
print(datetime.datetime.now(datetime.timezone.utc).timestamp() - datetime.datetime.utcnow().timestamp())
2 Answers

This behaviour is documented. It happens because utcnow() returns a naive datetime.

datetime.utcnow()

Return the current UTC date and time, with tzinfo None.

This is like now(), but returns the current UTC date and time, as a naive datetime object. An aware current UTC datetime can be obtained by calling datetime.now(timezone.utc).

That is why the documentation also says of datetime.now()

This function is preferred over today() and utcnow().

utcnow creates a naive datetime instance, because there was no UTC timezone object when it was introduced in Python. From the documentation for timestamp():

Naive datetime instances are assumed to represent local time and this method relies on the platform C mktime() function to perform the conversion.

Related