use chrono::NaiveDate;
use std::path::Path;
#[cfg(test)]
mod tests;
fn fti_digits(s: &str) -> bool {
s.len() >= 2 && s.chars().take(2).all(|i| i.is_ascii_digit())
}
pub fn parse(par: &str, fin: &str) -> Option<NaiveDate> {
if !fti_digits(fin) || par.len() < 4 {
return None;
}
let y = par.parse::<i32>().ok()?;
let m = fin[..2].parse::<u32>().unwrap();
let mut dayinf = &fin[2..];
if dayinf.starts_with(|i| matches!(i, '-' | '_')) {
dayinf = &dayinf[1..];
}
if !fti_digits(dayinf) {
return None;
}
let d = dayinf[..2].parse::<u32>().unwrap();
chrono::NaiveDate::from_ymd_opt(y, m, d)
}
pub fn parse_from_path(x: &Path) -> Option<NaiveDate> {
let mut fin = x;
let mut fins = fin.file_name()?.to_str()?;
if !fti_digits(fins) {
fin = x.parent()?;
fins = fin.file_name()?.to_str()?;
if !fti_digits(fins) {
return None;
}
}
let par = fin.parent()?.file_name()?.to_str()?;
parse(par, fins)
}
#[cfg(feature = "camino")]
pub fn parse_from_utf8path(x: &camino::Utf8Path) -> Option<NaiveDate> {
let mut fin = x;
let mut fins = fin.file_name()?;
if !fti_digits(fins) {
fin = x.parent()?;
fins = fin.file_name()?;
if !fti_digits(fins) {
return None;
}
}
let par = fin.parent()?.file_name()?;
parse(par, fins)
}
pub fn fmt(date: &NaiveDate, daysep: Option<char>) -> String {
let tmp;
date.format(if let Some(daysep) = daysep {
assert!(matches!(daysep, '-' | '_'));
tmp = format!("%Y/%m{}%d", daysep);
&tmp
} else {
"%Y/%m%d"
})
.to_string()
}