Bug report
Bug description:
The datetime.time documentation specifies:
If both comparands are aware and have different tzinfo attributes, the comparands are first adjusted by subtracting their UTC offsets.
UTC offsets have supported seconds and microseconds since Python 3.7 (gh-49538), but parts of the datetime.time implementation handle them incorrectly.
The C implementation can consider different normalized times equal and give them different hashes:
from datetime import time, timedelta, timezone
a = time(0, tzinfo=timezone(timedelta(microseconds=1)))
b = time(0, tzinfo=timezone(timedelta(microseconds=2)))
print(a == b) # True, expected False
print(hash(a) == hash(b)) # False, despite a == b
The pure Python implementation also compares valid values incorrectly and raises an internal assertion while hashing:
import _pydatetime as datetime
a = datetime.time(12, tzinfo=datetime.timezone.utc)
b = datetime.time(
12, 0, 1,
tzinfo=datetime.timezone(datetime.timedelta(seconds=1)),
)
print(a == b) # False, expected True
hash(b) # AssertionError: whole minute
The comparison should use the complete normalized value wall time - UTC offset. The pure Python comparison uses minute floor division for the offset, while the C comparison omits the offset's microseconds. The pure Python hash also assumes a whole-minute offset.
I am working on a PR with regression tests for both implementations.
CPython versions tested on:
CPython main branch
Operating systems tested on:
Linux
Linked PRs
Bug report
Bug description:
The
datetime.timedocumentation specifies:UTC offsets have supported seconds and microseconds since Python 3.7 (gh-49538), but parts of the
datetime.timeimplementation handle them incorrectly.The C implementation can consider different normalized times equal and give them different hashes:
The pure Python implementation also compares valid values incorrectly and raises an internal assertion while hashing:
The comparison should use the complete normalized value
wall time - UTC offset. The pure Python comparison uses minute floor division for the offset, while the C comparison omits the offset's microseconds. The pure Python hash also assumes a whole-minute offset.I am working on a PR with regression tests for both implementations.
CPython versions tested on:
CPython main branch
Operating systems tested on:
Linux
Linked PRs