Skip to content

Make Timezone and FixedTimezone hashable (#1008) - #1019

Closed
mishra-prince wants to merge 2 commits into
python-pendulum:masterfrom
mishra-prince:fix/timezone-hashable-1008
Closed

mishra-prince wants to merge 2 commits into
python-pendulum:masterfrom
mishra-prince:fix/timezone-hashable-1008

Conversation

@mishra-prince

Copy link
Copy Markdown

Fixes #1008.

Timezone and FixedTimezone became unhashable in 3.1.0:

>>> import pendulum
>>> hash(pendulum.Timezone("UTC"))
TypeError: unhashable type: 'Timezone'

They were hashable in 3.0.0. The regression comes from commit 6383c07, which added __eq__ to these classes without a matching __hash__. Per the Python data model, defining __eq__ without __hash__ sets __hash__ to None, making instances unhashable — so they can no longer be used as dict keys or set members.

Change

Define __hash__ on both Timezone and FixedTimezone, consistent with each class's __eq__:

  • Timezone compares by key, so it hashes on (class, key).
  • FixedTimezone compares by _offset, so it hashes on (class, _offset).

This keeps the invariant that equal objects hash equally.

Tests

Added test_hashable to tests/tz/test_timezone.py, covering both classes: equal timezones hash equally and can be used in sets. Full tests/tz and tests/datetime/test_timezone.py pass locally (641 passed, 3 skipped). No new ruff errors introduced in the changed files.

Both classes define __eq__ but not __hash__, which makes Python set
__hash__ to None and the instances unhashable (a regression since 3.1.0
when __eq__ was added). Restore hashability by defining __hash__
consistently with __eq__ on both classes.

Fixes python-pendulum#1008
Copilot AI lite review requested due to automatic review settings September 28, 2026 12:42

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

Adjust hashing to remain consistent with equality across Timezone subclasses.

Review effort: Lite
Findings: 1 Medium severity

Open (1)
What changed in this PR

Restores hashability for Timezone and FixedTimezone, with regression tests for hashing and set membership.

Changes:

  • Adds __hash__ implementations to both timezone classes.
  • Adds hashability and set behavior tests.
File Reviewed changes
tests/​tz/​test_timezone.py Adds hashability and set-membership coverage.
src/​pendulum/​tz/​timezone.py Adds hashing methods; subclass equality can violate the equality/hash invariant.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread src/pendulum/tz/timezone.py Outdated
Comment on lines +72 to +73
def __hash__(self) -> int:
return hash((self.__class__, self.key))
__eq__ matches any Timezone/FixedTimezone with the same key/offset,
including subclasses, so the hash must not depend on the concrete class.
Hash the key (Timezone) and offset (FixedTimezone) directly.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Timezones are not hashable

2 participants