diff --git a/src/memories.rs b/src/memories.rs index 2e46328..ea31f65 100644 --- a/src/memories.rs +++ b/src/memories.rs @@ -204,16 +204,21 @@ pub fn extract_date_from_filename(filename: &str) -> Option= 13 - && let Some(date_time) = timestamp_str[0..13] + // Skip autogenerated filenames that start with "10000" (e.g., 1000004178.jpg) + // These are not timestamps but auto-generated file IDs + if timestamp_str.starts_with("10000") { + return None; + } + + // Try milliseconds first (13 digits exactly) + if len == 13 + && let Some(date_time) = timestamp_str .parse::() .ok() .and_then(DateTime::from_timestamp_millis) @@ -222,8 +227,10 @@ pub fn extract_date_from_filename(filename: &str) -> Option= 10 + // For 14-16 digits, treat first 10 digits as seconds to avoid far future dates + // Examples: att_1422489664680106 (16 digits), att_142248967186928 (15 digits) + if len >= 14 + && len <= 16 && let Some(date_time) = timestamp_str[0..10] .parse::() .ok() @@ -232,6 +239,28 @@ pub fn extract_date_from_filename(filename: &str) -> Option() + .ok() + .and_then(|timestamp_secs| DateTime::from_timestamp(timestamp_secs, 0)) + .map(|naive_dt| naive_dt.fixed_offset()) + { + return Some(date_time); + } + + // 11-12 digits: try as milliseconds (might be partial millisecond timestamp) + if (len == 11 || len == 12) + && let Some(date_time) = timestamp_str + .parse::() + .ok() + .and_then(DateTime::from_timestamp_millis) + .map(|naive_dt| naive_dt.fixed_offset()) + { + return Some(date_time); + } } None @@ -752,6 +781,55 @@ mod tests { assert_eq!(date_time.second(), 0); } + #[test] + fn test_extract_date_from_filename_attachment_15_digits() { + // att_142248967186928.jpeg - 15 digits, should parse first 10 as seconds + // 1422489671 = 2015-01-28 23:07:51 UTC (converts to local timezone) + let filename = "att_142248967186928.jpeg"; + let date_time = extract_date_from_filename(filename).unwrap(); + + // Verify year and month are correct (2015-01) + assert_eq!(date_time.year(), 2015); + assert_eq!(date_time.month(), 1); + // Day may be 28 or 29 depending on timezone + assert!(date_time.day() >= 28 && date_time.day() <= 29); + + // Verify timestamp is within expected range (should be around 1422489671) + let timestamp = date_time.timestamp(); + assert!(timestamp >= 1422480000 && timestamp <= 1422576000); // Jan 28-29, 2015 + } + + #[test] + fn test_extract_date_from_filename_attachment_16_digits() { + // att_1422489664680106.jpeg - 16 digits, should parse first 10 as seconds + // 1422489664 = 2015-01-28 23:07:44 UTC (converts to local timezone) + let filename = "att_1422489664680106.jpeg"; + let date_time = extract_date_from_filename(filename).unwrap(); + + // Verify year and month are correct (2015-01) + assert_eq!(date_time.year(), 2015); + assert_eq!(date_time.month(), 1); + // Day may be 28 or 29 depending on timezone + assert!(date_time.day() >= 28 && date_time.day() <= 29); + + // Verify timestamp is within expected range (should be around 1422489664) + let timestamp = date_time.timestamp(); + assert!(timestamp >= 1422480000 && timestamp <= 1422576000); // Jan 28-29, 2015 + } + + #[test] + fn test_extract_date_from_filename_autogenerated_should_not_match() { + // Autogenerated filenames like 1000004178.jpg should NOT be parsed as timestamps + // These start with "10000" which would be Sept 2001 if parsed literally + let filename = "1000004178.jpg"; + let date_time = extract_date_from_filename(filename); + + assert!( + date_time.is_none(), + "Autogenerated filenames starting with 10000 should not be parsed as dates" + ); + } + #[test] fn test_memory_date_priority_filename() { let temp_dir = tempdir().unwrap();