use crate::time::TimeSpan::{Infinite, Finite}; #[derive(Debug, Copy, Clone, Hash, Ord, PartialOrd, Eq, PartialEq)] pub enum TimeSpan { Infinite, Finite(FiniteTimeSpan) } #[derive(Default, Debug, Copy, Clone, Hash, Ord, PartialOrd, Eq, PartialEq)] pub struct FiniteTimeSpan { pub years: usize, pub months: usize, pub weeks: usize, pub days: usize, pub hours: usize, pub minutes: usize, pub seconds: usize, pub milliseconds: usize, pub microseconds: usize, pub nanoseconds: usize, } impl FiniteTimeSpan { pub fn with_years(&self, years: usize) -> FiniteTimeSpan { let mut new = self.clone(); new.years = years; new } pub fn with_months(&self, months: usize) -> FiniteTimeSpan { let mut new = self.clone(); new.months = months; new } pub fn with_weeks(&self, weeks: usize) -> FiniteTimeSpan { let mut new = self.clone(); new.weeks = weeks; new } pub fn with_days(&self, days: usize) -> FiniteTimeSpan { let mut new = self.clone(); new.days = days; new } pub fn with_hours(&self, hours: usize) -> FiniteTimeSpan { let mut new = self.clone(); new.hours = hours; new } pub fn with_minutes(&self, minutes: usize) -> FiniteTimeSpan { let mut new = self.clone(); new.minutes = minutes; new } pub fn with_seconds(&self, seconds: usize) -> FiniteTimeSpan { let mut new = self.clone(); new.seconds = seconds; new } pub fn with_milliseconds(&self, milliseconds: usize) -> FiniteTimeSpan { let mut new = self.clone(); new.milliseconds = milliseconds; new } pub fn with_microseconds(&self, microseconds: usize) -> FiniteTimeSpan { let mut new = self.clone(); new.microseconds = microseconds; new } pub fn with_nanoseconds(&self, nanoseconds: usize) -> FiniteTimeSpan { let mut new = self.clone(); new.nanoseconds = nanoseconds; new } pub fn new() -> FiniteTimeSpan { FiniteTimeSpan { years: 0, months: 0, weeks: 0, days: 0, hours: 0, minutes: 0, seconds: 0, milliseconds: 0, microseconds: 0, nanoseconds: 0, } } } pub fn parse_time_span(val: &str) -> Option { if val.trim() == "infinite" || val.trim() == "infinity" { Some(Infinite) } else { parse_finite_time_span(val).map(|x| Finite(x)) } } pub fn parse_finite_time_span(val: &str) -> Option { let parse = val.replace(" ", ""); let mut time_span = FiniteTimeSpan::default(); let mut current_value = String::new(); let mut current_num = 0usize; let finish = &mut |name: &str, amount: usize| { match name { "nsec" | "ns" => { time_span.nanoseconds += amount; } "usec" | "us" | "µs" => { time_span.microseconds += amount; } "msec" | "ms" => { time_span.milliseconds += amount; } "" | "s" | "sec" | "second" | "seconds" => { time_span.seconds += amount; } "minutes" | "minute" | "min" | "m" => { time_span.minutes += amount; } "hours" | "hour" | "hr" | "h" => { time_span.hours += amount; } "days" | "day" | "d" => { time_span.days += amount; } "weeks" | "week" | "w" => { time_span.weeks += amount; } "M" | "months" | "month" => { time_span.months += amount; } "years" | "year" | "y" => { time_span.years += amount; } _ => return false } true }; let mut last_is_nr = false; for chxr in parse.chars() { match chxr.to_ascii_lowercase() { '0'..='9' => { if !last_is_nr { if !finish(current_value.as_str(), current_num) { return None; } current_value = String::new(); current_num = 0; last_is_nr = true } current_num *= 10; current_num += chxr.to_digit(10).unwrap_or(0) as usize } 'a'..='z' => { current_value += &chxr.to_string(); last_is_nr = false; } _ => { return None; } } } if !finish(current_value.as_str(), current_num) { None } else { Some(time_span) } }