use std::time::Duration;
pub const MIN_INTERVAL: Duration = Duration::from_secs(30);
pub fn parse_duration(value: &str) -> Result<Duration, String> {
let value = value.trim();
if value.is_empty() {
return Err("empty duration".to_owned());
}
let mut total = Duration::ZERO;
let mut digits = String::new();
for ch in value.chars() {
match ch {
'0'..='9' => digits.push(ch),
's' | 'm' | 'h' => {
let amount: u64 = digits
.parse()
.map_err(|_| format!("invalid duration {value:?}"))?;
digits.clear();
let unit = match ch {
's' => 1,
'm' => 60,
_ => 3600,
};
total += Duration::from_secs(amount * unit);
}
_ => {
return Err(format!(
"invalid duration {value:?}; use forms like 45s, 10m, 2h"
))
}
}
}
if !digits.is_empty() {
let amount: u64 = digits
.parse()
.map_err(|_| format!("invalid duration {value:?}"))?;
total += Duration::from_secs(amount);
}
if total.is_zero() {
return Err("duration must be greater than zero".to_owned());
}
Ok(total)
}
pub fn parse_interval(value: &str) -> Result<Duration, String> {
Ok(parse_duration(value)?.max(MIN_INTERVAL))
}