rspec/rules/S6887/python/rule.adoc

48 lines
2.5 KiB
Plaintext

This rule raises an issue when passing a `pytz.timezone` to the `datetime.datetime` constructor.
== Why is this an issue?
When working with timezones in Python, it's important to understand that the `datetime.datetime` constructor and `pytz` timezone objects handle timezones differently. This difference can lead to unexpected results if a `pytz` object is used as the `tzinfo` argument in the `datetime.datetime` constructor.
The `datetime.datetime` constructor expects a `tzinfo` object that is a subclass of the `datetime.tzinfo` base class. `pytz` timezone objects do provide this interface, but they implement it in a way that's not fully compatible with `datetime.datetime`.
One key difference is how they handle historical changes in timezone offsets. The `datetime` module uses the IANA time zone database, which includes historical changes.
When you create a `datetime` object with a `pytz` timezone object as the `tzinfo` argument, it uses the earliest known offset for that timezone. This can lead to unexpected offsets, as the earliest known offset may not match the current or most commonly used offset for that timezone.
For example, if you were to use 'US/Eastern' as your timezone, you might expect the offset to be either -5 hours (Eastern Standard Time) or -4 hours (Eastern Daylight Time), depending on the time of the year. However, due to historical changes, the actual offset might be something different, like -4 hours and 56 minutes. This can lead to subtle bugs in your code, especially if you're doing calculations with datetime objects.
Note that, when using Python 3.9 and later, it is recommended to use the `zoneinfo` package from the standard library over `pytz`.
== How to fix it
To avoid these issues, it's recommended to use the localize method of `pytz` timezone objects to attach a timezone to a `datetime` object. This method correctly handles historical changes and other timezone-related issues.
=== Code examples
==== Noncompliant code example
[source,python,diff-id=1,diff-type=noncompliant]
----
import datetime
import pytz
dt = datetime.datetime(2022, 1, 1, tzinfo=pytz.timezone('US/Eastern')) # Noncompliant: 2022-01-01 00:00:00-04:56
----
==== Compliant solution
[source,python,diff-id=1,diff-type=compliant]
----
import datetime
import pytz
dt = pytz.timezone('US/Eastern').localize(datetime.datetime(2022, 1, 1)) # OK: 2022-01-01 00:00:00-05:00
----
== Resources
=== Documentation
* PEP 615 - https://peps.python.org/pep-0615/[Support for the IANA Time Zone Database in the Standard Library]