time_parse/duration/
mod.rs

1mod duration_hand;
2mod duration_nom;
3
4use std::str::FromStr;
5
6const SECS_PER_MINUTE: u64 = 60;
7const SECS_PER_HOUR: u64 = 60 * SECS_PER_MINUTE;
8const SECS_PER_DAY: u64 = 24 * SECS_PER_HOUR;
9const SECS_PER_WEEK: u64 = 7 * SECS_PER_DAY;
10
11pub use self::duration_hand::parse;
12pub use self::duration_nom::parse as parse_nom;
13
14/// AsRef<str> but implementable on nom types
15/// Workaround for https://github.com/Geal/nom/pull/753
16trait Strable {
17    fn as_str(&self) -> &str;
18}
19
20impl<'s> Strable for &'s str {
21    fn as_str(&self) -> &str {
22        self
23    }
24}
25
26impl<'s> Strable for dyn AsRef<str> {
27    fn as_str(&self) -> &str {
28        self.as_ref()
29    }
30}
31
32fn to_nanos<S: Strable>(s: S) -> Option<u32> {
33    let s = s.as_str();
34
35    const NANO_DIGITS: usize = 9;
36    if s.len() > NANO_DIGITS {
37        return None;
38    }
39
40    let extra_zeros = (NANO_DIGITS - s.len()) as u32;
41    let mul = 10u32.pow(extra_zeros);
42    match u32::from_str(s) {
43        Ok(num) => Some(num * mul),
44        Err(_) => None,
45    }
46}
47
48#[cfg(test)]
49mod tests {
50    #[test]
51    fn test_nanos() {
52        use super::to_nanos;
53        assert_eq!(0, to_nanos("0").unwrap());
54        assert_eq!(0, to_nanos("000").unwrap());
55
56        assert_eq!(1, to_nanos("000000001").unwrap());
57        assert_eq!(10, to_nanos("00000001").unwrap());
58        assert_eq!(100, to_nanos("0000001").unwrap());
59        assert_eq!(1000, to_nanos("000001").unwrap());
60        assert_eq!(10000, to_nanos("00001").unwrap());
61        assert_eq!(100000, to_nanos("0001").unwrap());
62        assert_eq!(1000000, to_nanos("001").unwrap());
63        assert_eq!(10000000, to_nanos("01").unwrap());
64        assert_eq!(100000000, to_nanos("1").unwrap());
65
66        assert_eq!(7_010, to_nanos("00000701").unwrap());
67    }
68}