use chrono::Duration;
use std::fmt;
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Frequency {
Secondly,
Minutely,
Hourly,
Daily,
Weekly,
Monthly,
Quarterly,
Yearly,
Custom(Duration),
}
impl Frequency {
pub fn from_str(s: &str) -> Option<Self> {
match s.to_uppercase().as_str() {
"S" | "SEC" | "SECOND" | "SECONDS" => Some(Frequency::Secondly),
"T" | "MIN" | "MINUTE" | "MINUTES" => Some(Frequency::Minutely),
"H" | "HOUR" | "HOURS" => Some(Frequency::Hourly),
"D" | "DAY" | "DAYS" | "DAILY" => Some(Frequency::Daily),
"W" | "WEEK" | "WEEKS" | "WEEKLY" => Some(Frequency::Weekly),
"M" | "MONTH" | "MONTHS" | "MONTHLY" => Some(Frequency::Monthly),
"Q" | "QUARTER" | "QUARTERS" | "QUARTERLY" => Some(Frequency::Quarterly),
"Y" | "YEAR" | "YEARS" | "A" | "ANNUAL" | "ANNUALLY" | "YEARLY" => {
Some(Frequency::Yearly)
}
_ => {
parse_custom_frequency(s)
}
}
}
pub fn to_seconds(&self) -> i64 {
match self {
Frequency::Secondly => 1,
Frequency::Minutely => 60,
Frequency::Hourly => 3600,
Frequency::Daily => 86400,
Frequency::Weekly => 604800,
Frequency::Monthly => 2592000, Frequency::Quarterly => 7776000, Frequency::Yearly => 31536000, Frequency::Custom(duration) => duration.num_seconds(),
}
}
}
impl fmt::Display for Frequency {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Frequency::Secondly => write!(f, "S"),
Frequency::Minutely => write!(f, "T"),
Frequency::Hourly => write!(f, "H"),
Frequency::Daily => write!(f, "D"),
Frequency::Weekly => write!(f, "W"),
Frequency::Monthly => write!(f, "M"),
Frequency::Quarterly => write!(f, "Q"),
Frequency::Yearly => write!(f, "Y"),
Frequency::Custom(duration) => write!(f, "{}s", duration.num_seconds()),
}
}
}
fn parse_custom_frequency(s: &str) -> Option<Frequency> {
let mut num_chars = String::new();
let mut unit_chars = String::new();
let mut found_digit = false;
for c in s.chars() {
if c.is_digit(10) {
found_digit = true;
num_chars.push(c);
} else if found_digit {
unit_chars.push(c);
} else {
return None;
}
}
if num_chars.is_empty() || unit_chars.is_empty() {
return None;
}
let num: i64 = match num_chars.parse() {
Ok(n) => n,
Err(_) => return None,
};
match unit_chars.to_uppercase().as_str() {
"S" | "SEC" | "SECOND" | "SECONDS" => Some(Frequency::Custom(Duration::seconds(num))),
"T" | "MIN" | "MINUTE" | "MINUTES" => Some(Frequency::Custom(Duration::minutes(num))),
"H" | "HOUR" | "HOURS" => Some(Frequency::Custom(Duration::hours(num))),
"D" | "DAY" | "DAYS" => Some(Frequency::Custom(Duration::days(num))),
"W" | "WEEK" | "WEEKS" => Some(Frequency::Custom(Duration::weeks(num))),
_ => None,
}
}