midenc_session/
duration.rs

1use std::{
2    fmt,
3    time::{Duration, Instant},
4};
5
6#[derive(Copy, Clone)]
7pub struct HumanDuration(Duration);
8impl HumanDuration {
9    pub fn since(i: Instant) -> Self {
10        Self(Instant::now().duration_since(i))
11    }
12
13    /// Get this duration as an f64 representing the duration in fractional seconds
14    #[inline]
15    pub fn as_secs_f64(&self) -> f64 {
16        self.0.as_secs_f64()
17    }
18
19    /// Adds two [HumanDuration], using saturating arithmetic
20    #[inline]
21    pub fn saturating_add(self, rhs: Self) -> Self {
22        Self(self.0.saturating_add(rhs.0))
23    }
24}
25impl core::ops::Add for HumanDuration {
26    type Output = HumanDuration;
27
28    fn add(self, rhs: Self) -> Self::Output {
29        Self(self.0 + rhs.0)
30    }
31}
32impl core::ops::Add<Duration> for HumanDuration {
33    type Output = HumanDuration;
34
35    fn add(self, rhs: Duration) -> Self::Output {
36        Self(self.0 + rhs)
37    }
38}
39impl core::ops::AddAssign for HumanDuration {
40    fn add_assign(&mut self, rhs: Self) {
41        self.0 += rhs.0;
42    }
43}
44impl core::ops::AddAssign<Duration> for HumanDuration {
45    fn add_assign(&mut self, rhs: Duration) {
46        self.0 += rhs;
47    }
48}
49impl From<HumanDuration> for Duration {
50    fn from(d: HumanDuration) -> Self {
51        d.0
52    }
53}
54impl From<Duration> for HumanDuration {
55    fn from(d: Duration) -> Self {
56        Self(d)
57    }
58}
59impl fmt::Debug for HumanDuration {
60    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
61        fmt::Display::fmt(self, f)
62    }
63}
64impl fmt::Display for HumanDuration {
65    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
66        let t = self.0.as_secs();
67        let alt = f.alternate();
68        macro_rules! try_unit {
69            ($secs:expr, $sg:expr, $pl:expr, $s:expr) => {
70                let cnt = t / $secs;
71                if cnt == 1 {
72                    if alt {
73                        return write!(f, "{}{}", cnt, $s);
74                    } else {
75                        return write!(f, "{} {}", cnt, $sg);
76                    }
77                } else if cnt > 1 {
78                    if alt {
79                        return write!(f, "{}{}", cnt, $s);
80                    } else {
81                        return write!(f, "{} {}", cnt, $pl);
82                    }
83                }
84            };
85        }
86
87        if t > 0 {
88            try_unit!(365 * 24 * 60 * 60, "year", "years", "y");
89            try_unit!(7 * 24 * 60 * 60, "week", "weeks", "w");
90            try_unit!(24 * 60 * 60, "day", "days", "d");
91            try_unit!(60 * 60, "hour", "hours", "h");
92            try_unit!(60, "minute", "minutes", "m");
93            try_unit!(1, "second", "seconds", "s");
94        } else {
95            // Time was too precise for the standard path, use millis
96            let t = self.0.as_millis();
97            if t > 0 {
98                return write!(f, "{}{}", t, if alt { "ms" } else { " milliseconds" });
99            }
100        }
101        write!(f, "0{}", if alt { "s" } else { " seconds" })
102    }
103}