1use std::time::Duration;
7
8pub fn parse_duration(s: &str) -> Option<Duration> {
12 let s = s.trim();
13
14 if let Ok(secs) = s.parse::<f64>() {
15 return if secs >= 0.0 {
16 Some(Duration::from_secs_f64(secs))
17 } else {
18 None
19 };
20 }
21
22 if let Some(num) = s.strip_suffix("ms") {
23 let ms: u64 = num.trim().parse().ok()?;
24 return Some(Duration::from_millis(ms));
25 }
26 if let Some(num) = s.strip_suffix('s') {
27 let secs: f64 = num.trim().parse().ok()?;
28 return if secs >= 0.0 {
29 Some(Duration::from_secs_f64(secs))
30 } else {
31 None
32 };
33 }
34 if let Some(num) = s.strip_suffix('m') {
35 let mins: f64 = num.trim().parse().ok()?;
36 return if mins >= 0.0 {
37 Some(Duration::from_secs_f64(mins * 60.0))
38 } else {
39 None
40 };
41 }
42 if let Some(num) = s.strip_suffix('h') {
43 let hours: f64 = num.trim().parse().ok()?;
44 return if hours >= 0.0 {
45 Some(Duration::from_secs_f64(hours * 3600.0))
46 } else {
47 None
48 };
49 }
50
51 None
52}
53
54#[cfg(test)]
55mod tests {
56 use super::*;
57
58 #[test]
59 fn seconds() {
60 assert_eq!(parse_duration("30"), Some(Duration::from_secs(30)));
61 assert_eq!(parse_duration("0"), Some(Duration::from_secs(0)));
62 assert_eq!(parse_duration("1.5"), Some(Duration::from_secs_f64(1.5)));
63 }
64
65 #[test]
66 fn suffixes() {
67 assert_eq!(parse_duration("500ms"), Some(Duration::from_millis(500)));
68 assert_eq!(parse_duration("5s"), Some(Duration::from_secs(5)));
69 assert_eq!(parse_duration("2m"), Some(Duration::from_secs(120)));
70 assert_eq!(parse_duration("1h"), Some(Duration::from_secs(3600)));
71 }
72
73 #[test]
74 fn invalid() {
75 assert_eq!(parse_duration("abc"), None);
76 assert_eq!(parse_duration(""), None);
77 assert_eq!(parse_duration("-5"), None);
78 assert_eq!(parse_duration("5x"), None);
79 }
80}