Dates: true_instant on metadata responses for instant matching
The mobile viewer anchored its "messages around this photo" window on the legacy date_taken (a wall clock stored as UTC for EXIF rows), while SMS-API dates are true instants: the window was off by the photo's UTC offset (4-5 h for photos taken at home; ImageApi #113 user story 3). Verified SMS-API side: importers store backup epochs as UTC, and 40/40 sampled rows equal their source epochs exactly. `/image/metadata` (+ GPS / date mutation responses) now carries `true_instant` from `date_view::file_true_instant`: `row_true_instant`, else the filename-class instant, else the earliest fs time. Server-side for the same reason as `wall_clock`: the drain's permanent floor rows have no `date_utc`. `set_capture_dates` fills both fields at all four response sites. dev/e2e: the manifest records each fixture's expected instant (the wall read in its GPS zone, else America/New_York) and `e2e.sh check` asserts it (97/97). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
8fc512fef0
commit
e3477a4710
5 files changed
+117
-18
No files matched your search
@@ -1,9 +1,10 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Regression check for the displayed capture time (ADR-0001 `wall_clock`).
|
||||
"""Regression check for capture dates (ADR-0001 `wall_clock` / `true_instant`).
|
||||
|
||||
For every indexed fixture, the manifest's expected wall clock must equal the
|
||||
`wall_clock` the server reports on each endpoint that includes the file:
|
||||
`/image/metadata`, `/memories` (today's day span) and `/photos/gps-summary`.
|
||||
`/image/metadata`, `/memories` (today's day span) and `/photos/gps-summary`;
|
||||
and `/image/metadata`'s `true_instant` must equal the expected instant.
|
||||
One disagreement anywhere is exactly the class of bug this field exists to
|
||||
end, so any mismatch fails the run.
|
||||
|
||||
@@ -35,17 +36,21 @@ def main() -> int:
|
||||
failures = 0
|
||||
for item in items:
|
||||
path, want = item["path"], item["wall_clock"]
|
||||
got = {"metadata": api("image/metadata?path=" + urllib.parse.quote(path)).get("wall_clock")}
|
||||
meta = api("image/metadata?path=" + urllib.parse.quote(path))
|
||||
got = {"metadata": meta.get("wall_clock")}
|
||||
if path in memories:
|
||||
got["memories"] = memories[path]
|
||||
if path in gps:
|
||||
got["gps-summary"] = gps[path]
|
||||
bad = {k: v for k, v in got.items() if v != want}
|
||||
# The matching anchor (SMS / location windows) must be the true instant.
|
||||
if meta.get("true_instant") != item["true_instant"]:
|
||||
bad["metadata true_instant"] = (meta.get("true_instant"), "expected", item["true_instant"])
|
||||
if bad:
|
||||
failures += 1
|
||||
print(f"MISMATCH {path}: expected {want}, got {bad}")
|
||||
|
||||
print(f"{len(items) - failures}/{len(items)} fixtures report the expected wall clock "
|
||||
print(f"{len(items) - failures}/{len(items)} fixtures report the expected wall clock + instant "
|
||||
f"({len(memories)} in memories, {len(gps)} in gps-summary)")
|
||||
return 1 if failures else 0
|
||||
|
||||
|
||||
Reference in new issue
Block a user