Skip to content

Fix strpfromiso silently corrupting non-UTC timestamps - #562

Merged
fit-alessandro-berti merged 1 commit into
process-intelligence-solutions:releasefrom
mittalpk:fix/strpfromiso-utc-offset-conversion
Jul 27, 2026
Merged

Fix strpfromiso silently corrupting non-UTC timestamps#562
fit-alessandro-berti merged 1 commit into
process-intelligence-solutions:releasefrom
mittalpk:fix/strpfromiso-utc-offset-conversion

Conversation

@mittalpk

Copy link
Copy Markdown
Contributor

Fixes #561

Summary

strpfromiso (the default ISO8601 date parser for Python >= 3.7) silently corrupts any timestamp that has a non-UTC offset, whenever ENABLE_DATETIME_COLUMNS_AWARE is enabled — which is the default for everyone except cuDF/RAPIDS installs.

fix_naivety() called dt.replace(tzinfo=timezone.utc) on an already-aware datetime. replace() only relabels the timezone; it does not convert the wall-clock value. A timestamp like 2026-07-23T10:00:00+05:00 (which is 05:00 UTC) was silently stored as 2026-07-23T10:00:00+00:00 — shifted by 5 hours, with no warning or error.

Fix

Only relabel (assume UTC) when the parsed value has no offset at all (nothing to convert from — same behavior as before for naive input). When it does have an offset, convert via astimezone(timezone.utc), matching the already-correct tz_convert("UTC") behavior in the sibling fix_dataframe_column() function a few lines above it in the same file.

Testing

Added tests/dt_parsing_test.py covering:

  • positive and negative non-UTC offsets (the bug case)
  • the existing Z-suffix path (still correct)
  • naive input with no offset at all (unchanged behavior — treated as already UTC, not reinterpreted through the host's local timezone)
  • the ENABLE_DATETIME_COLUMNS_AWARE = False branch (unchanged)

Verified the two offset-conversion tests fail against the pre-fix code and pass against the fix. Also ran the existing business_hours_test.py and xes_impexp_test.py/xes_deep_coverage_test.py suites (downstream consumers of this parser) — all pass, no regressions.

How did I verify: python -m pytest tests/dt_parsing_test.py tests/business_hours_test.py tests/xes_impexp_test.py tests/xes_deep_coverage_test.py -v from the tests/ directory, all green.

…-intelligence-solutions#561)

fix_naivety() used replace(tzinfo=timezone.utc) on already-aware
datetimes, which relabels the timezone without converting the
wall-clock value. A timestamp like 2026-07-23T10:00:00+05:00
(05:00 UTC) was silently stored as 2026-07-23T10:00:00+00:00,
shifted by the source offset.

Fix: only relabel (assume UTC) when the parsed value has no offset
at all; convert via astimezone() when it does, matching the
already-correct tz_convert("UTC") behavior in the sibling
fix_dataframe_column() function.

Adds regression tests covering positive/negative offsets, the
existing Z-suffix path, naive input, and the aware-disabled branch.

Signed-off-by: Praveen Mittal <pkmittal28@gmail.com>
@fit-alessandro-berti

Copy link
Copy Markdown
Contributor

Dear @mittalpk thank you for your report.

Could you start the contribution level agreement as in https://processintelligence.solutions/pm4py/contributing ?

@mittalpk

Copy link
Copy Markdown
Contributor Author

Thanks @fit-alessandro-berti
I just sent a review/CLA request to info@processintelligence.solutions referencing this PR.
Happy to provide anything else needed in the meantime.

@fit-alessandro-berti
fit-alessandro-berti merged commit 24ef8fe into process-intelligence-solutions:release Jul 27, 2026
fit-alessandro-berti pushed a commit that referenced this pull request Jul 27, 2026
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.

Bug: strpfromiso date parser silently corrupts non-UTC timestamps (replace() instead of astimezone())

2 participants