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
bc41c737e5
commit
9269b5c9fd
5 files changed
+117
-18
No files matched your search
@@ -47,6 +47,15 @@ PLACES = {
|
||||
"tokyo": (35.6595, 139.7005),
|
||||
}
|
||||
|
||||
# IANA zone of each place — what the server's GPS rung of the offset cascade
|
||||
# resolves, so the expected true instant is the wall read in this zone.
|
||||
PLACE_ZONES = {
|
||||
"santa_monica": "America/Los_Angeles",
|
||||
"paris": "Europe/Paris",
|
||||
"yosemite": "America/Los_Angeles",
|
||||
"tokyo": "Asia/Tokyo",
|
||||
}
|
||||
|
||||
PALETTE = [
|
||||
"0x1f4e79", "0x7a3e9d", "0x2e7d32", "0xb71c1c", "0xe65100",
|
||||
"0x006064", "0x4e342e", "0x283593", "0x827717", "0xad1457",
|
||||
@@ -182,6 +191,15 @@ def expected_wall_clock(it: Item) -> str:
|
||||
return wall.strftime("%Y-%m-%dT%H:%M:%S")
|
||||
|
||||
|
||||
def expected_true_instant(it: Item) -> int:
|
||||
"""The true instant the server should report: the expected wall read in
|
||||
the zone the camera was in (GPS place, else HOME_TZ — the server's
|
||||
assumed zone). Filename walls outrank EXIF, but still take GPS evidence."""
|
||||
wall = dt.datetime.fromisoformat(expected_wall_clock(it))
|
||||
zone = ZoneInfo(PLACE_ZONES[it.gps]) if it.gps else HOME_TZ
|
||||
return int(wall.replace(tzinfo=zone).timestamp())
|
||||
|
||||
|
||||
def _same_day(today: dt.date, year: int, hour: int) -> dt.datetime:
|
||||
# Feb 29 in a non-leap year would be invalid; fall back to Feb 28.
|
||||
try:
|
||||
@@ -332,6 +350,7 @@ def main() -> int:
|
||||
"tags": it.tags, "duplicate_of": it.copy_of,
|
||||
# A duplicate carries its source's bytes, EXIF included.
|
||||
"wall_clock": expected_wall_clock(by_path.get(it.copy_of, it)),
|
||||
"true_instant": expected_true_instant(by_path.get(it.copy_of, it)),
|
||||
}
|
||||
for it in items
|
||||
],
|
||||
|
||||
Reference in new issue
Block a user