feat(dates): foundation for the true-instant date contract (#114)
Populate the new-contract date columns at ingest while keeping the legacy date_taken column byte-identical (ADR-0001): - camera_tz module: offset cascade (offset tag -> GPS zone -> server zone) as a pure, testable function; bundled offline TZF geometry for GPS -> IANA resolution; DST-correct offsets for the capture date; display-zone helpers (DEFAULT_DISPLAY_TZ, display_zone_for, display_zone_offset_minutes) for the read-side cutover. - EXIF branch: kamadak-exif now collects OffsetTime* tags paired with the winning date tag; resolve_date_taken takes an ExifPrior and emits (date_utc, camera_offset_minutes, date_taken_tz_source) per branch: exif -> cascade, exiftool/fs_time -> utc_direct, filename -> unclassified (pending #116). - Schema: migration adds image_exif.date_utc / camera_offset_minutes / date_taken_tz_source and user_ai_prefs.display_tz (all nullable; down.sql drops them). - DAO + ingest: backfill_date_taken persists the triple alongside the legacy pair; watcher, upload, and set_image_gps call sites feed the cascade. - Response surface: ExifMetadata and ExifSummary carry the triple so /image/metadata and /photos/exif expose it (null for unconverted rows); reel requests mirror display_tz into prefs. cargo build + clippy clean; 625 lib + 702 bin tests pass (the one failing doctest in utils.rs is pre-existing at the base commit).
This commit is contained in:
1 parent
ee773a34ef
commit
2f2107d4fa
20 files changed
+1039
-36
No files matched your search
+13
-2
@@ -787,10 +787,16 @@ pub fn process_new_files(
|
||||
// computed above) → exiftool fallback for videos / MakerNote /
|
||||
// QuickTime → filename regex → earliest_fs_time. Source is
|
||||
// recorded so the per-tick backfill drain can re-run weak
|
||||
// resolutions later.
|
||||
// resolutions later. The EXIF branch additionally runs the
|
||||
// camera-offset cascade to produce the new-contract columns
|
||||
// (date_utc / camera_offset_minutes / date_taken_tz_source,
|
||||
// ADR-0001) while the legacy date_taken stays byte-identical.
|
||||
let resolved_date = date_resolver::resolve_date_taken(
|
||||
&file_path,
|
||||
exif_fields.as_ref().and_then(|e| e.date_taken),
|
||||
exif_fields
|
||||
.as_ref()
|
||||
.and_then(date_resolver::exif_prior_from)
|
||||
.as_ref(),
|
||||
);
|
||||
|
||||
let insert_exif = InsertImageExif {
|
||||
@@ -827,6 +833,11 @@ pub fn process_new_files(
|
||||
phash_64: perceptual.map(|h| h.phash_64),
|
||||
dhash_64: perceptual.map(|h| h.dhash_64),
|
||||
date_taken_source: resolved_date.map(|r| r.source.as_str().to_string()),
|
||||
date_utc: resolved_date.and_then(|r| r.date_utc),
|
||||
camera_offset_minutes: resolved_date.and_then(|r| r.camera_offset_minutes),
|
||||
date_taken_tz_source: resolved_date
|
||||
.and_then(|r| r.tz_source)
|
||||
.map(|t| t.as_str().to_string()),
|
||||
};
|
||||
|
||||
let mut dao = exif_dao.lock().expect("Unable to lock ExifDao");
|
||||
|
||||
Reference in new issue
Block a user