fix(dates): prefer earliest of fs created/modified as fallback

On copied or restored files (e.g. a backup library), the OS stamps
created at copy time while modified is preserved from the source, so
the earlier of the two is a better proxy for when the content
originated. Adds utils::earliest_fs_time and threads it through the
three spots that fall back to filesystem dates: photos-list sort,
memories grouping, and insight-generation timestamp.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Cameron
2026-04-23 17:20:12 -04:00
parent d54419e779
commit dc2a96162e
4 changed files with 31 additions and 9 deletions

View File

@@ -23,7 +23,7 @@ use crate::libraries::Library;
use crate::memories::extract_date_from_filename;
use crate::otel::global_tracer;
use crate::tags::TagDao;
use crate::utils::normalize_path;
use crate::utils::{earliest_fs_time, normalize_path};
#[derive(Deserialize)]
struct NominatimResponse {
@@ -760,8 +760,6 @@ impl InsightGenerator {
let full_path = self.resolve_full_path(&file_path)?;
File::open(&full_path)
.and_then(|f| f.metadata())
.and_then(|m| m.created().or(m.modified()))
.map(|t| DateTime::<Utc>::from(t).timestamp())
.inspect_err(|e| {
log::warn!(
"Failed to get file timestamp for insight {}: {}",
@@ -770,6 +768,8 @@ impl InsightGenerator {
)
})
.ok()
.and_then(|m| earliest_fs_time(&m))
.map(|t| DateTime::<Utc>::from(t).timestamp())
})
.unwrap_or_else(|| Utc::now().timestamp())
};
@@ -1687,7 +1687,11 @@ Return ONLY the summary, nothing else."#,
let date = chrono::DateTime::from_timestamp(h.date, 0)
.map(|dt| dt.format("%Y-%m-%d").to_string())
.unwrap_or_else(|| h.date.to_string());
let direction: &str = if h.type_ == 2 { &user_name } else { &h.contact_name };
let direction: &str = if h.type_ == 2 {
&user_name
} else {
&h.contact_name
};
let score = h
.similarity_score
.map(|s| format!(" [score {:.2}]", s))
@@ -2858,8 +2862,6 @@ Return ONLY the summary, nothing else."#,
let full_path = self.resolve_full_path(&file_path)?;
File::open(&full_path)
.and_then(|f| f.metadata())
.and_then(|m| m.created().or(m.modified()))
.map(|t| DateTime::<Utc>::from(t).timestamp())
.inspect_err(|e| {
log::warn!(
"Failed to get file timestamp for agentic insight {}: {}",
@@ -2868,6 +2870,8 @@ Return ONLY the summary, nothing else."#,
)
})
.ok()
.and_then(|m| earliest_fs_time(&m))
.map(|t| DateTime::<Utc>::from(t).timestamp())
})
.unwrap_or_else(|| Utc::now().timestamp())
};