def __hash__(self): if self._hashcode == -1: tzoff = self.utcoffset() if tzoff is None: self._hashcode = hash(self.replace(first=True)._getstate()[0]) else: days = _ymd2ord(self.year, self.month, self.day) seconds = self.hour * 3600 + self.minute * 60 + self.second self._hashcode = hash(timedelta(days, seconds, self.microsecond) - tzoff) return self._hashcode
... I think I admitted defeat too soon. Can you present a specific case where "two datetimes that compare true have different hashes"?
Two aware datetimes in a single zone representing the earlier and later ambiguous time. All fields (including tzinfo) are identical except for fold. "==" says True. But `tzoff` differs between them, so the code above passes different values to `hash()`. It's not guaranteed that the hashes differ, but it's very likely they differ.
There may be some subtlety due to the fact that we ignore tzinfo in == if it is the same for both sides,
That's why they compare equal in this case.
but when we compute hash(), we don't know what's on the other side. It is hard to tell without a specific example. I thought I got it right when I wrote the code above, but it is possible I missed some case.
It's a puzzle ;-)