time_hms/
lib.rs

1use std::fmt;
2
3/// TimeHms parses a duration in seconds to a more human-readable representation
4/// in hours, minutes and seconds.
5/// ```
6/// use time_hms::TimeHms;
7///
8/// let t = TimeHms::new(3723);
9///
10/// // 3723 seconds equal 1 hour, 2 minutes and 3 seconds
11/// assert_eq!(t.h(), 1);
12/// assert_eq!(t.m(), 2);
13/// assert_eq!(t.s(), 3);
14///
15/// // A default way to format! / println! is included
16/// assert_eq!(format!("{}", t), "01:02:03")
17///```
18#[derive(Debug, PartialEq)]
19pub struct TimeHms {
20    h: u64,
21    m: u64,
22    s: u64,
23}
24
25impl TimeHms {
26    /// Converts a duration from a representation in seconds
27    /// into a representation in hours, minutes and seconds.
28    pub fn new(seconds: u64) -> TimeHms {
29        let (m, s) = divmod(seconds, 60);
30        let (h, m) = divmod(m, 60);
31
32        TimeHms { h, m, s }
33    }
34
35    /// Returns the hour part of the duration.
36    pub fn h(&self) -> u64 {
37        self.h
38    }
39
40    /// Returns the minute part of the duration.
41    pub fn m(&self) -> u64 {
42        self.m
43    }
44
45    /// Returns the seconds part of the duration.
46    pub fn s(&self) -> u64 {
47        self.s
48    }
49}
50
51impl fmt::Display for TimeHms {
52    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
53        write!(f, "{:0>2}:{:0>2}:{:0>2}", self.h, self.m, self.s)
54    }
55}
56
57/// Takes two numbers as arguments and returns their quotient and remainder when using integer division.
58fn divmod(x: u64, y: u64) -> (u64, u64) {
59    let quotient = x / y;
60    let remainder = x % y;
61    (quotient, remainder)
62}
63
64#[cfg(test)]
65mod tests {
66    use super::*;
67
68    #[test]
69    fn test_divmod() {
70        let test_cases = vec![
71            (5, 2, (2, 1)),
72            (10, 3, (3, 1)),
73            (13, 5, (2, 3)),
74            (0, 5, (0, 0)),
75            (u64::MAX, 1, (u64::MAX, 0)),
76            (u64::MAX, u64::MAX, (1, 0)),
77        ];
78
79        for (x, y, expected) in test_cases {
80            assert_eq!(divmod(x, y), expected);
81        }
82    }
83
84    #[test]
85    fn timehms_new() {
86        let test_cases = vec![
87            (0, (0, 0, 0)),
88            (12345, (3, 25, 45)),
89            (123456789, (34293, 33, 9)),
90        ];
91
92        for (input, expected) in test_cases {
93            let t = TimeHms::new(input);
94            let (h, m, s) = expected;
95            assert_eq!(t.h(), h);
96            assert_eq!(t.m(), m);
97            assert_eq!(t.s(), s);
98        }
99    }
100
101    #[test]
102    fn equal() {
103        let t1 = TimeHms::new(3661);
104        let t2 = TimeHms::new(3661);
105        assert_eq!(t1, t2);
106    }
107
108    #[test]
109    fn not_equal() {
110        let t1 = TimeHms::new(3661);
111        let t2 = TimeHms::new(3662);
112        assert_ne!(t1, t2);
113    }
114}