| use std::time::Duration; |
| |
| use crate::CargoResult; |
| |
| /// Parses a time span string. |
| pub fn parse_time_span(span: &str) -> CargoResult<Duration> { |
| maybe_parse_time_span(span).ok_or_else(|| { |
| anyhow::format_err!( |
| "expected a value of the form \ |
| \"N seconds/minutes/hours/days/weeks/months\", got: {span:?}" |
| ) |
| }) |
| } |
| |
| /// Parses a time span string. |
| /// |
| /// Returns None if the value is not valid. See [`parse_time_span`] if you |
| /// need a variant that generates an error message. |
| pub fn maybe_parse_time_span(span: &str) -> Option<Duration> { |
| let Some(right_i) = span.find(|c: char| !c.is_ascii_digit()) else { |
| return None; |
| }; |
| let (left, mut right) = span.split_at(right_i); |
| if right.starts_with(' ') { |
| right = &right[1..]; |
| } |
| let count: u64 = left.parse().ok()?; |
| let factor = match right { |
| "second" | "seconds" => 1, |
| "minute" | "minutes" => 60, |
| "hour" | "hours" => 60 * 60, |
| "day" | "days" => 24 * 60 * 60, |
| "week" | "weeks" => 7 * 24 * 60 * 60, |
| "month" | "months" => 2_629_746, // average is 30.436875 days |
| _ => return None, |
| }; |
| Some(Duration::from_secs(factor * count)) |
| } |
| |
| #[cfg(test)] |
| mod tests { |
| use super::*; |
| |
| #[test] |
| fn time_spans() { |
| let d = |x| Some(Duration::from_secs(x)); |
| assert_eq!(maybe_parse_time_span("0 seconds"), d(0)); |
| assert_eq!(maybe_parse_time_span("1second"), d(1)); |
| assert_eq!(maybe_parse_time_span("23 seconds"), d(23)); |
| assert_eq!(maybe_parse_time_span("5 minutes"), d(60 * 5)); |
| assert_eq!(maybe_parse_time_span("2 hours"), d(60 * 60 * 2)); |
| assert_eq!(maybe_parse_time_span("1 day"), d(60 * 60 * 24)); |
| assert_eq!(maybe_parse_time_span("2 weeks"), d(60 * 60 * 24 * 14)); |
| assert_eq!(maybe_parse_time_span("6 months"), d(2_629_746 * 6)); |
| } |
| |
| #[test] |
| fn time_span_errors() { |
| assert_eq!(maybe_parse_time_span(""), None); |
| assert_eq!(maybe_parse_time_span("1"), None); |
| assert_eq!(maybe_parse_time_span("second"), None); |
| assert_eq!(maybe_parse_time_span("+2 seconds"), None); |
| assert_eq!(maybe_parse_time_span("day"), None); |
| assert_eq!(maybe_parse_time_span("-1 days"), None); |
| assert_eq!(maybe_parse_time_span("1.5 days"), None); |
| assert_eq!(maybe_parse_time_span("1 dayz"), None); |
| assert_eq!(maybe_parse_time_span("always"), None); |
| assert_eq!(maybe_parse_time_span("never"), None); |
| assert_eq!(maybe_parse_time_span("1 day "), None); |
| assert_eq!(maybe_parse_time_span(" 1 day"), None); |
| assert_eq!(maybe_parse_time_span("1 second"), None); |
| } |
| } |