flake8 plugin which checks that datetime.utcnow()
and datetime.utcfromtimestamp()
are not used. It suggests using datetime.now(timezone.utc)
and datetime.fromtimestamp(ts, tz=timezone.utc)
instead respectively.
Also, utcnow
and utcfromtimestamp
are finally deprecated in Python 3.12:
- PR: python/cpython#103858
- Issue: python/cpython#103857
note: timezone must be imported from datetime
first:
from datetime import datetime
from datetime import timezone
datetime.now(timezone.utc)
from datetime import datetime
from datetime import timezone
datetime.fromtimestamp(1684079261, tz=timezone.utc)
pip install flake8-ban-utcnow
Code | Description |
---|---|
UTC001 | don't use datetime.datetime.utcnow(), use datetime.datetime.now(datetime.timezone.utc) instead or datetime.now(datetime.UTC) on >= 3.11. |
UTC002 | don't use datetime.datetime.utcfromtimestamp(), use datetime.datetime.fromtimestamp(..., tz=datetime.timezone.utc) instead or datetime.datetime.fromtimestamp(..., tz=datetime.UTC) on >= 3.11. |
See pre-commit for instructions
Sample .pre-commit-config.yaml
:
- repo: https://github.com/pycqa/flake8
rev: 6.0.0
hooks:
- id: flake8
additional_dependencies: [flake8-ban-utcnow==0.2.0]
One could expect that when explicitly calling datetime.utcnow()
the datetime
object would be timezone aware, but it's not! A common pitfall is, deriving a
timestamp from the datetime
object created using datetime.utcnow()
.
-
the computer is in
CEST
and we want to derive adatetime
in UTC formatted as a timestamp hence callingutcnow().timestamp()
.>>> from datetime import datetime >>> datetime.utcnow() datetime.datetime(2022, 8, 7, 23, 40, 17, 7858) >>> datetime.utcnow().timestamp() 1659908656.048843
-
if we convert the timestamp, it says this, which is obviously incorrect.
GMT: Sunday, 7. August 2022 21:44:16 Your time zone: Sunday, 7. August 2022 23:44:16 GMT+02:00 DST Relative: 2 hours ago
-
converting it using python and
datetime.fromtimestamp
, we by accident get the correct datetime in UTC>>> datetime.fromtimestamp(1659908656.048843) datetime.datetime(2022, 8, 7, 23, 44, 16, 48843)
-
being aware that the timestamp should be in
UTC
we callutcfromtimestamp
instead and get the result as above, since the timestamp actually is in local time, but unaware of this.>>> datetime.utcfromtimestamp(1659908656.048843) datetime.datetime(2022, 8, 7, 21, 44, 16, 48843)
-
the computer is in
CEST
and we want to actually derive adatetime
in UTC formatted as a timestamp.>>> from datetime import timezone >>> from datetime import datetime >>> datetime.now(timezone.utc).timestamp() 1659916399.651218
-
we now get what we actually expect
GMT: Sunday, 7. August 2022 23:53:19 Your time zone: Monday, 8. August 2022 01:53:19 GMT+02:00 DST Relative: A few seconds ago
-
the next thing to keep in mind is, that only timezone-aware
datetime
objects can be compared hence using this forces us to always make sure all objects are timezone aware.