Skip to content

normalize_date_to_iso silently re-anchors an unresolvable timezone abbreviation to UTC #252

Description

@cdeust

What

mcp_server/core/temporal.normalize_date_to_iso silently reinterprets a timezone
abbreviation it cannot resolve as UTC, and persists the wrong instant.

Reproduce

$ python -W error::Warning -c "
from mcp_server.core.temporal import normalize_date_to_iso
print(normalize_date_to_iso('8 May 2023 13:56 EST'))"

dateutil emits UnknownTimezoneWarning: tzname EST identified but not understood
and drops the zone; the default=_DATEUTIL_ANCHOR fill (added in the #239 DTZ
family) then supplies UTC. The value written to memories.created_at is
2023-05-08T13:56:00+00:00 — five hours off, with no signal reaching the caller.

Why it was not fixed in the DTZ PR

The obvious inline fix, wrapping the parse in warnings.catch_warnings() +
simplefilter("error", UnknownTimezoneWarning), mutates process-global
filter state and is documented as not thread-safe. Doing that inside a store
write path is worse than the defect it closes. The correct fix is a tzinfos
policy, and choosing one is a real decision (which EST? which CST?), not a
lint cleanup.

Outside the DTZ family's blast radius: no producer in the repo emits a zone
abbreviation in created_at (LoCoMo emits 1:56 pm on 8 May, 2023, LongMemEval
emits 2023/04/10 (Mon) 17:50 — neither states a zone), and no test, build or
lint step that PR triggers reaches the path. Filed per coding-standards §14.3.

Acceptance criteria

  1. A created_at carrying an unresolvable timezone abbreviation either resolves
    correctly through an explicit tzinfos mapping, or is rejected as
    unparseable — never silently re-anchored to UTC.
  2. Whichever behaviour is chosen emits an actionable signal, and a test asserts
    the emission itself (§13 F1), not only a downstream effect.
  3. No warnings.catch_warnings() on a store write path.
  4. A regression test that fails against the current implementation.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions