rspec/rules/S6903/python/rule.adoc
github-actions[bot] 6cef4fd8ca
Create rule S6903: Using timezone-aware "datetime" objects should be preferred over using "datetime.datetime.utcnow" and "datetime.datetime.utcfromtimestamp" (#3597)
* Create rule S6903

* Create rule S6903: Using timezone aware "datetime"s should be preferred over using "datetime.datetime.utcnow" and "datetime.datetime.utcfromtimestamp"

* Fix after review

* Minor updates

---------

Co-authored-by: joke1196 <joke1196@users.noreply.github.com>
Co-authored-by: David Kunzmann <david.kunzmann@sonarsource.com>
Co-authored-by: Guillaume Dequenne <guillaume.dequenne@sonarsource.com>
2024-03-11 11:53:04 +01:00

61 lines
1.8 KiB
Plaintext

This rule raises an issue when the functions `datetime.datetime.utcnow` or `datetime.datetime.utcfromtimestamp` are used.
== Why is this an issue?
Python's `datetime` API provide several different ways to create `datetime` objects. One possibility is the to use
`datetime.datetime.utcnow` or `datetime.datetime.utcfromtimestamp` functions. The issue with these two functions is they are not time zone aware, even if their name would suggest otherwise.
Using these functions could cause issue as they may not behave as expected, for example:
[source,python]
----
from datetime import datetime
timestamp = 1571595618.0
date = datetime.utcfromtimestamp(timestamp)
date_timestamp = date.timestamp()
assert timestamp == date_timestamp
----
This assertion will fail if the system locale is not set to UTC.
For this reason these 2 functions are deprecated in Python 3.12.
== How to fix it
To fix this issue, prefer the usage of a timezone-aware datetime.
=== Code examples
==== Noncompliant code example
[source,python,diff-id=1,diff-type=noncompliant]
----
from datetime import datetime
datetime.utcnow() # Noncompliant
timestamp = 1571595618.0
datetime.utcfromtimestamp(timestamp) # Noncompliant
----
==== Compliant solution
[source,python,diff-id=1,diff-type=compliant]
----
from datetime import datetime, timezone
datetime.now(timezone.utc) # Compliant
timestamp = 1571595618.0
datetime.fromtimestamp(timestamp, timezone.utc) # Compliant
----
== Resources
=== Documentation
* Python documentation - https://docs.python.org/3/library/datetime.html#datetime.datetime.utcnow[utcnow reference]
* Python documentation - https://docs.python.org/3/library/datetime.html#datetime.datetime.utcfromtimestamp[utcfromtimestamp reference]
=== Articles & blog posts
* Paul Ganssle blog - https://blog.ganssle.io/articles/2019/11/utcnow.html[Stop using utcnow and utcfromtimestamp]