use chrono::{DateTime, Utc}; use std::fs; use std::path::Path; /// Returns the age of a path as a [DateTime]. /// - If the path doesn't exist, returns [None] /// - If it's a file, returns the modified time /// - If it's a directory, returns the LATEST modified time of all files within pub fn path_ts_latest(path: impl AsRef) -> Result>, std::io::Error> { let path = path.as_ref(); if !path.exists() { return Ok(None); } let metadata = fs::metadata(path)?; if metadata.is_file() { let modified = metadata.modified()?; Ok(Some(modified.into())) } else if metadata.is_dir() { find_latest_modified(path) } else { Ok(None) } } /// Returns the age of a path as a [DateTime]. /// - If the path doesn't exist, returns [None] /// - If it's a file, returns the modified time /// - If it's a directory, returns the EARLIEST modified time of all files within pub fn path_ts_earliest(path: impl AsRef) -> Result>, std::io::Error> { let path = path.as_ref(); if !path.exists() { return Ok(None); } let metadata = fs::metadata(path)?; if metadata.is_file() { let modified = metadata.modified()?; Ok(Some(modified.into())) } else if metadata.is_dir() { find_earliest_modified(path) } else { Ok(None) } } fn find_latest_modified(dir: &Path) -> Result>, std::io::Error> { let mut latest: Option> = None; // Include the directory's own modification time let dir_metadata = fs::metadata(dir)?; if let Ok(modified) = dir_metadata.modified() { let dt: DateTime = modified.into(); latest = Some(dt); } let entries = fs::read_dir(dir)?; for entry in entries.flatten() { let path = entry.path(); let metadata = entry.metadata()?; if metadata.is_file() { if let Ok(modified) = metadata.modified() { let dt: DateTime = modified.into(); latest = Some(match latest { Some(prev) if prev > dt => prev, _ => dt, }); } } else if metadata.is_dir() && let Some(dir_latest) = find_latest_modified(&path)? { latest = Some(match latest { Some(prev) if prev > dir_latest => prev, _ => dir_latest, }); } } return Ok(latest); } fn find_earliest_modified(dir: &Path) -> Result>, std::io::Error> { let mut earliest: Option> = None; // Include the directory's own modification time let dir_metadata = fs::metadata(dir)?; if let Ok(modified) = dir_metadata.modified() { let dt: DateTime = modified.into(); earliest = Some(dt); } let entries = fs::read_dir(dir)?; for entry in entries.flatten() { let path = entry.path(); let metadata = entry.metadata()?; if metadata.is_file() { if let Ok(modified) = metadata.modified() { let dt: DateTime = modified.into(); earliest = Some(match earliest { Some(prev) if prev < dt => prev, _ => dt, }); } } else if metadata.is_dir() && let Some(dir_earliest) = find_earliest_modified(&path)? { earliest = Some(match earliest { Some(prev) if prev < dir_earliest => prev, _ => dir_earliest, }); } } return Ok(earliest); }