From 93957bf3894107803de00f5a352651cb78bb4e47 Mon Sep 17 00:00:00 2001 From: Cameron Date: Fri, 15 Aug 2025 23:20:07 -0400 Subject: [PATCH] Refactor date parsing from filename by introducing reusable closure, remove redundant logging level, and simplify regex logic. --- src/memories.rs | 89 +++++++++++++++++++------------------------------ 1 file changed, 34 insertions(+), 55 deletions(-) diff --git a/src/memories.rs b/src/memories.rs index 2468b41..6066840 100644 --- a/src/memories.rs +++ b/src/memories.rs @@ -2,7 +2,7 @@ use actix_web::web::Data; use actix_web::{get, web, HttpRequest, HttpResponse, Responder}; use chrono::LocalResult::{Ambiguous, Single}; use chrono::{DateTime, Datelike, FixedOffset, Local, LocalResult, NaiveDate, TimeZone, Utc}; -use log::{debug, info, trace, warn}; +use log::{debug, trace, warn}; use opentelemetry::trace::{Span, Status, Tracer}; use opentelemetry::KeyValue; use serde::{Deserialize, Serialize}; @@ -111,81 +111,60 @@ fn get_file_date_info( } fn extract_date_from_filename(filename: &str) -> Option> { + let build_date_from_ymd_capture = + |captures: ®ex::Captures| -> Option> { + let year = captures.get(1)?.as_str().parse::().ok()?; + let month = captures.get(2)?.as_str().parse::().ok()?; + let day = captures.get(3)?.as_str().parse::().ok()?; + let hour = captures.get(4)?.as_str().parse::().ok()?; + let min = captures.get(5)?.as_str().parse::().ok()?; + let sec = captures.get(6)?.as_str().parse::().ok()?; + + match Local.from_local_datetime( + &NaiveDate::from_ymd_opt(year, month, day)?.and_hms_opt(hour, min, sec)?, + ) { + Single(dt) => Some(dt.fixed_offset()), + Ambiguous(early_dt, _) => Some(early_dt.fixed_offset()), + LocalResult::None => { + warn!("Weird local date: {:?}", filename); + None + } + } + }; + // 1. Screenshot format: Screenshot_2014-06-01-20-44-50.png if let Some(captures) = regex::Regex::new(r"Screenshot_(\d{4})-(\d{2})-(\d{2})-(\d{2})-(\d{2})-(\d{2})") .ok()? .captures(filename) + .and_then(|c| build_date_from_ymd_capture(&c)) { - let year = captures.get(1)?.as_str().parse::().ok()?; - let month = captures.get(2)?.as_str().parse::().ok()?; - let day = captures.get(3)?.as_str().parse::().ok()?; - let hour = captures.get(4)?.as_str().parse::().ok()?; - let min = captures.get(5)?.as_str().parse::().ok()?; - let sec = captures.get(6)?.as_str().parse::().ok()?; - - return match Local.from_local_datetime( - &NaiveDate::from_ymd_opt(year, month, day)?.and_hms_opt(hour, min, sec)?, - ) { - Single(dt) => Some(dt.fixed_offset()), - Ambiguous(early_dt, _) => Some(early_dt.fixed_offset()), - LocalResult::None => { - warn!("Weird local date: {:?}", filename); - return None; - } - }; + return Some(captures); } // 2. Dash format: 2015-01-09_02-15-15.jpg if let Some(captures) = regex::Regex::new(r"(\d{4})-(\d{2})-(\d{2})_(\d{2})-(\d{2})-(\d{2})") .ok()? .captures(filename) + .and_then(|c| build_date_from_ymd_capture(&c)) { - let year = captures.get(1)?.as_str().parse::().ok()?; - let month = captures.get(2)?.as_str().parse::().ok()?; - let day = captures.get(3)?.as_str().parse::().ok()?; - let hour = captures.get(4)?.as_str().parse::().ok()?; - let min = captures.get(5)?.as_str().parse::().ok()?; - let sec = captures.get(6)?.as_str().parse::().ok()?; - - return match Local.from_local_datetime( - &NaiveDate::from_ymd_opt(year, month, day)?.and_hms_opt(hour, min, sec)?, - ) { - Single(dt) => Some(dt.fixed_offset()), - Ambiguous(early_dt, _) => Some(early_dt.fixed_offset()), - LocalResult::None => { - warn!("Weird local date: {:?}", filename); - return None; - } - }; + return Some(captures); } // 3. Compact format: 20140927101712.jpg if let Some(captures) = regex::Regex::new(r"(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})") .ok()? .captures(filename) + .and_then(|c| build_date_from_ymd_capture(&c)) { - let year = captures.get(1)?.as_str().parse::().ok()?; - let month = captures.get(2)?.as_str().parse::().ok()?; - let day = captures.get(3)?.as_str().parse::().ok()?; - let hour = captures.get(4)?.as_str().parse::().ok()?; - let min = captures.get(5)?.as_str().parse::().ok()?; - let sec = captures.get(6)?.as_str().parse::().ok()?; - - return match Local.from_local_datetime( - &NaiveDate::from_ymd_opt(year, month, day)?.and_hms_opt(hour, min, sec)?, - ) { - Single(dt) => Some(dt.fixed_offset()), - Ambiguous(early_dt, _) => Some(early_dt.fixed_offset()), - LocalResult::None => { - warn!("Weird local date: {:?}", filename); - return None; - } - }; + return Some(captures); } - // 4. Timestamp format: xyz_1401638400.jpeg - if let Some(captures) = regex::Regex::new(r"_(\d{10,})\.").ok()?.captures(filename) { + // 4. Timestamp format: 1401638400.jpeg + if let Some(captures) = regex::Regex::new(r"(\d{10}|\d{13})\.") + .ok()? + .captures(filename) + { let timestamp_str = captures.get(1)?.as_str(); // Millisecond timestamp (13 digits) @@ -340,7 +319,7 @@ fn is_memories_match( } let years_diff = (today.year() - file_date.year()).unsigned_abs(); if years_diff > years_back { - info!( + warn!( "File date is too far in the past: {:?} vs {:?}", file_date, today );