Skip to content

Accept the Z designator in timestamptz strings - #4015

Open
anishmehta24 wants to merge 2 commits into
apache:mainfrom
anishmehta24:fix/timestamptz-utc-designator
Open

anishmehta24 wants to merge 2 commits into
apache:mainfrom
anishmehta24:fix/timestamptz-utc-designator

Conversation

@anishmehta24

Copy link
Copy Markdown

Rationale for this change

Timestamptz strings that end in Z are rejected, even though Z is the ISO-8601 designator for UTC and Java's OffsetDateTime.parse accepts it:

table.scan(row_filter="ts >= '2023-06-01T00:00:00Z'")
# ValueError: Invalid timestamp with zone: 2023-06-01T00:00:00Z (must be ISO-8601)

The same filter with +00:00 works. ISO_TIMESTAMPTZ and ISO_TIMESTAMPTZ_NANO now accept Z as well as +HH:MM/-HH:MM. Z is swapped for +00:00 before calling datetime.fromisoformat, because on Python 3.10 fromisoformat doesn't accept Z.

Are these changes tested?

Yes. There are new cases in tests/utils/test_datetime.py for timestamptz_to_micros and timestamptz_to_nanos with Z, and they fail without the change. The datetime, literal, transform and conversion tests pass (735). I also checked the Z case on Python 3.10.

Are there any user-facing changes?

Yes. Timestamptz literals and row filters now accept a trailing Z.

Copilot AI lite review requested due to automatic review settings September 24, 2026 21:00

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot review overview

🟢 Approval recommended

No unresolved issues were identified.

Review effort: Lite
Findings: None

What changed in this PR

Adds support for trailing Z UTC designators in timestamptz parsing.

Changes:

  • Accept Z in microsecond and nanosecond timestamp formats.
  • Normalize Z to +00:00 for Python 3.10 compatibility.
  • Add conversion tests for Z timestamps.
File Description
tests/​utils/​test_datetime.py Tests Z-terminated timestamptz conversions.
pyiceberg/​utils/​datetime.py Supports and normalizes Z timestamps.

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

Comment thread pyiceberg/utils/datetime.py Outdated
ISO_TIMESTAMPTZ = re.compile(r"\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(.\d{1,6})?[-+]\d{2}:\d{2}")
ISO_TIMESTAMPTZ_NANO = re.compile(r"(\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2})(.\d{1,6})?(\d{1,3})?([-+]\d{2}:\d{2})")
ISO_TIMESTAMPTZ = re.compile(r"\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(.\d{1,6})?([-+]\d{2}:\d{2}|Z)")
ISO_TIMESTAMPTZ_NANO = re.compile(r"(\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2})(.\d{1,6})?(\d{1,3})?([-+]\d{2}:\d{2}|Z)")

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

It looks like Java also supports lowercase z (and no seconds). Could you add those while you're here?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Done, both timestamptz patterns now accept a lowercase z and leave out the seconds (a fraction still needs seconds before it, like in Java). Added cases for both to the tests.

This branch has not been deployed

No deployments
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.

3 participants