Skip to content

Fix _format_api_dates: parse ISO 8601 datetimes#247

Draft
thodson-usgs wants to merge 1 commit intoDOI-USGS:mainfrom
thodson-usgs:fix/format-api-dates-iso8601
Draft

Fix _format_api_dates: parse ISO 8601 datetimes#247
thodson-usgs wants to merge 1 commit intoDOI-USGS:mainfrom
thodson-usgs:fix/format-api-dates-iso8601

Conversation

@thodson-usgs
Copy link
Copy Markdown
Collaborator

@thodson-usgs thodson-usgs commented May 3, 2026

Summary

A single ISO 8601 datetime such as \"2018-02-12T23:20:50Z\" — the format the docstrings of every getter cite as a valid time example — was silently dropped to None. The function only tried \"%Y-%m-%d %H:%M:%S\" and \"%Y-%m-%d\", neither of which matches a string with a T separator and trailing Z. _construct_api_requests then set params[\"time\"] = None, requests dropped the param, and the user's time filter was silently discarded — the API fell back to "most recent year".

This PR replaces the cascading try/except with a single helper that walks the supported formats in order: ISO 8601 with offset and/or fractional seconds, plain ISO 8601, the legacy space-separated form, and date-only. Tz-aware inputs convert directly to UTC; naive inputs continue to be interpreted in the runner's local zone for backwards compatibility.

It also tightens the duration / interval pass-through. The previous re.search(r\"P\", ..., re.IGNORECASE) matched any string containing a p or P anywhere — words like \"Apr\" or \"sample\" would skip parsing entirely. The check is now anchored to ^[Pp]\\d.

Test plan

  • Ten new regression tests in tests/waterdata_utils_test.py cover: ISO 8601 with Z; with fractional seconds; with numeric offset; pair of ISO 8601 datetimes; passthrough of intervals / durations; words containing p are no longer mis-parsed; legacy space-separated form still works; date-only output.
  • Full local test suite passes (236 tests).

Related PRs

Other open PRs in this bug-review series that touch dataretrieval/waterdata/utils.py (different functions, no functional conflicts):

A single ISO 8601 datetime such as "2018-02-12T23:20:50Z" — the format
the docstrings of every getter cite as a valid `time` example — was
silently dropped to None. The function only tried "%Y-%m-%d %H:%M:%S"
and "%Y-%m-%d", neither of which matches a string with a `T` separator
and trailing `Z`. `_construct_api_requests` then set `params["time"] =
None`, requests dropped the param, and the user's time filter was
silently discarded — the API fell back to "most recent year".

Replace the cascading try/except with a single helper that walks the
supported formats in order: ISO 8601 with offset and/or fractional
seconds, plain ISO 8601, the legacy space-separated form, and date-only.
Tz-aware inputs convert directly to UTC; naive inputs continue to be
interpreted in the runner's local zone for backwards compatibility.

Also tighten the duration / interval pass-through. The previous
`re.search(r"P", ..., re.IGNORECASE)` matched any string containing a
`p` or `P` anywhere — words like "Apr" or "sample" would skip parsing
entirely. Anchor the check to `^[Pp]\d`.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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.

1 participant