1use std::time::Duration;
2
3use crate::CargoResult;
4
5pub fn parse_time_span(span: &str) -> CargoResult<Duration> {
7 maybe_parse_time_span(span).ok_or_else(|| {
8 anyhow::format_err!(
9 "expected a value of the form \
10 \"N seconds/minutes/hours/days/weeks/months\", got: {span:?}"
11 )
12 })
13}
14
15pub fn maybe_parse_time_span(span: &str) -> Option<Duration> {
20 let Some(right_i) = span.find(|c: char| !c.is_ascii_digit()) else {
21 return None;
22 };
23 let (left, mut right) = span.split_at(right_i);
24 if right.starts_with(' ') {
25 right = &right[1..];
26 }
27 let count: u64 = left.parse().ok()?;
28 let factor = match right {
29 "second" | "seconds" => 1,
30 "minute" | "minutes" => 60,
31 "hour" | "hours" => 60 * 60,
32 "day" | "days" => 24 * 60 * 60,
33 "week" | "weeks" => 7 * 24 * 60 * 60,
34 "month" | "months" => 2_629_746, _ => return None,
36 };
37 Some(Duration::from_secs(factor * count))
38}
39
40#[cfg(test)]
41mod tests {
42 use super::*;
43
44 #[test]
45 fn time_spans() {
46 let d = |x| Some(Duration::from_secs(x));
47 assert_eq!(maybe_parse_time_span("0 seconds"), d(0));
48 assert_eq!(maybe_parse_time_span("1second"), d(1));
49 assert_eq!(maybe_parse_time_span("23 seconds"), d(23));
50 assert_eq!(maybe_parse_time_span("5 minutes"), d(60 * 5));
51 assert_eq!(maybe_parse_time_span("2 hours"), d(60 * 60 * 2));
52 assert_eq!(maybe_parse_time_span("1 day"), d(60 * 60 * 24));
53 assert_eq!(maybe_parse_time_span("2 weeks"), d(60 * 60 * 24 * 14));
54 assert_eq!(maybe_parse_time_span("6 months"), d(2_629_746 * 6));
55 }
56
57 #[test]
58 fn time_span_errors() {
59 assert_eq!(maybe_parse_time_span(""), None);
60 assert_eq!(maybe_parse_time_span("1"), None);
61 assert_eq!(maybe_parse_time_span("second"), None);
62 assert_eq!(maybe_parse_time_span("+2 seconds"), None);
63 assert_eq!(maybe_parse_time_span("day"), None);
64 assert_eq!(maybe_parse_time_span("-1 days"), None);
65 assert_eq!(maybe_parse_time_span("1.5 days"), None);
66 assert_eq!(maybe_parse_time_span("1 dayz"), None);
67 assert_eq!(maybe_parse_time_span("always"), None);
68 assert_eq!(maybe_parse_time_span("never"), None);
69 assert_eq!(maybe_parse_time_span("1 day "), None);
70 assert_eq!(maybe_parse_time_span(" 1 day"), None);
71 assert_eq!(maybe_parse_time_span("1 second"), None);
72 }
73}