Skip to content

Normalize timestamps to UTC in the timestamp index - #323

Open
Bernhard Merkle (bmerkle) wants to merge 2 commits into
microsoft:mainfrom
bmerkle:fix-timestamp-index-utc-normalization
Open

Bernhard Merkle (bmerkle) wants to merge 2 commits into
microsoft:mainfrom
bmerkle:fix-timestamp-index-utc-normalization

Conversation

@bmerkle

Copy link
Copy Markdown
Collaborator

Fixes #320.

Problem

TimestampToTextRangeIndex sorts and bisects ISO strings, assuming lexicographic order equals chronological order. That only holds if all timestamps share one UTC offset. Email ingestion kept the sender's offset, so range lookups silently returned the wrong messages.

Changes

  • In-memory index: normalize stored timestamps and query bounds to fixed-format UTC (...T12:00:00.000000Z). Naive timestamps are treated as UTC, which also fixes the naive-vs-aware boundary case. Fixed microsecond precision avoids 12:00:00Z vs 12:00:00.5Z misordering.
  • email_import: normalize the Date header to UTC (-0000 treated as UTC), so the SQLite index (which also compares strings) gets consistent values.
  • Tests for mixed offsets, incremental inserts, naive/aware boundary, fractional seconds, and email date normalization.

Notes

  • Timestamps returned by the in-memory lookup_range are now normalized; one existing test assertion was updated accordingly.
  • Not addressed: existing SQLite databases with previously imported emails still hold +HH:MM strings alongside new Z ones. That would need a migration or normalize-on-read; happy to do it as a follow-up.

make passes (763 tests).

🤖 Generated with Claude Code

TimestampToTextRangeIndex sorted and bisected ISO strings, which only
works if every timestamp has the same UTC offset. Email ingestion kept
the sender's offset, so range lookups silently dropped in-range messages.

- Normalize stored timestamps and query bounds to fixed-format UTC
  (microseconds, "Z" suffix); naive timestamps are treated as UTC.
- Normalize email Date headers to UTC on import so the SQLite index,
  which compares strings too, gets consistent values.
- Add tests for mixed offsets, incremental inserts, naive/aware
  boundaries, fractional seconds and email date normalization.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Copilot AI balanced review requested due to automatic review settings September 28, 2026 21:58

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

🟡 Changes recommended

SQLite lookups remain incorrect when whole-second email timestamps are compared with fractional-second query bounds.

Review effort: Balanced
Findings: 1 High severity

Open (1)
What changed in this PR

Normalizes timestamps to UTC to preserve chronological ordering in string-based indexes.

Changes:

  • Normalizes in-memory timestamps and query bounds to fixed-width UTC.
  • Normalizes imported email dates to UTC.
  • Adds offset, boundary, fractional-second, and email tests.
File Description
src/​typeagent/​storage/​memory/​timestampindex.py Adds fixed-width UTC normalization.
src/​typeagent/​emails/​email_import.py Converts email dates to UTC.
tests/​test_timestampindex.py Tests timestamp ordering and boundaries.
tests/​test_email_import.py Tests email date normalization.

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

Comment thread src/typeagent/emails/email_import.py

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

The implementation consistently addresses the reported ordering failures with focused regression coverage.

Review effort: Balanced
Findings: 1 High severity

Open (1)

Stored start_timestamp values can have any UTC offset and fractional
precision (existing rows included), so raw string comparison misorders
e.g. "07:00:00Z" vs "07:00:00.500000Z". Compare via strftime(), which
converts to UTC and yields a fixed-width value, in lookup_range and
get_timestamp_ranges. Add a matching expression index so range queries
stay indexed; no data migration is needed.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

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.

Timestamp index silently drops in-range messages when timestamps carry different UTC offsets

2 participants