Skip to content

fix(python): normalize datetime params to UTC ISO with Z suffix - #2114

Open
VaggelisGian wants to merge 1 commit into
pmxt-dev:mainfrom
VaggelisGian:fix/python-datetime-utc-serialization
Open

fix(python): normalize datetime params to UTC ISO with Z suffix#2114
VaggelisGian wants to merge 1 commit into
pmxt-dev:mainfrom
VaggelisGian:fix/python-datetime-utc-serialization

Conversation

@VaggelisGian

Copy link
Copy Markdown

Fixes #2095, Fixes #2096

What was broken

Both issues share one root cause. The Python SDK serialized datetime request parameters with bare datetime.isoformat(): a timezone-less string for naive inputs and an offset suffix for aware inputs. The TypeScript SDK sends Date.toISOString(), which is always UTC with millisecond precision and a Z suffix. For the same wall-clock input the two SDKs could therefore request different instants (an aware 2026-01-02T12:00:00+09:00 went out verbatim from Python where TS sends 2026-01-02T03:00:00.000Z). The two sites were fetch_ohlcv start/end in client.py and the Router updatedSince filter in router.py; a repo-wide grep confirmed these are the only two request-serializing datetime sites.

What changed

Added _format_datetime_utc() next to the existing timestamp helpers in _hosted_mappers.py and applied it at both call sites. It mirrors the TS semantics: naive datetimes are treated as UTC, aware datetimes are converted with astimezone(UTC), bare dates count as UTC midnight (#2096's Python-only date acceptance is preserved but normalized rather than rejected), output always has millisecond precision with a Z suffix, matching Date.toISOString() byte for byte including .000. Strings and other query values pass through unchanged.

Tests

New sdks/python/tests/test_datetime_serialization.py following the mocking patterns of test_router_sql_orderbook.py (monkeypatched _api_client.call_api) and test_hosted_dispatch.py (Mock exchange with monkeypatched _sidecar_read_request). Covers fetch_ohlcv naive/aware/microsecond-truncation and router updatedSince naive/aware/bare-date/string-passthrough cases. Without the patch exactly 7 of the 8 fail with the old wire values listed above; with it all 8 pass.

Verification

  • python -m pytest tests/ from sdks/python: 273 passed; only failures are the two pre-existing HOME-vs-USERPROFILE sandbox cases that fail identically on clean main.
  • bash scripts/verify-all.sh on this branch matches a clean checkout of main exactly: only the three known Windows-only sandbox defects fail, which pass on ubuntu-latest CI.
  • No generated artifacts affected: all three edited files are hand-written runtime modules outside client.py's BEGIN/END GENERATED METHODS region.

fetch_ohlcv start/end and the Router updatedSince filters serialized
datetimes with a bare datetime.isoformat(), while the TypeScript SDK
sends Date.toISOString(): always UTC, millisecond precision, Z suffix.
For aware or non-UTC inputs the two SDKs could therefore request
different instants for the same wall-clock time.

Add _format_datetime_utc() next to the existing timestamp helpers in
_hosted_mappers.py and use it at both call sites. Naive datetimes are
treated as UTC, aware datetimes are converted to UTC, and bare dates
count as UTC midnight, so both SDKs now send identical values. Strings
and other query values pass through unchanged.

Fixes pmxt-dev#2095
Fixes pmxt-dev#2096
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant