1use std::fmt::{self, Display, Formatter};
3use std::time::{Duration, Instant};
4
5use time::OffsetDateTime;
6
7#[derive(Clone, Copy)]
12pub(crate) struct Timer {
13 start_monotonic: Instant,
21 start_formattable: OffsetDateTime,
22}
23
24impl Timer {
25 pub(crate) fn new() -> Timer {
27 Timer {
28 start_monotonic: Instant::now(),
29 start_formattable: OffsetDateTime::now_utc(),
30 }
31 }
32
33 pub(crate) fn elapsed(&self) -> Timing {
35 let duration = self.start_monotonic.elapsed();
36 Timing(duration)
37 }
38
39 pub(crate) fn start_time(&self) -> &OffsetDateTime {
41 &self.start_formattable
42 }
43}
44
45#[derive(Clone, Copy)]
47pub(crate) struct Timing(Duration);
48
49impl Display for Timing {
50 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
51 let duration = self.0;
52 match duration.as_micros() {
53 i if i < 1000 => {
54 write!(f, "{}µs", i)
55 }
56 i if i < 1_000_000 => {
57 write!(f, "{:.2}ms", (i as f64) / 1000.0)
58 }
59 _ => {
60 write!(f, "{:.2}s", duration.as_secs_f32())
61 }
62 }
63 }
64}
65
66#[cfg(test)]
67mod tests {
68 use std::time::Duration;
69
70 use super::Timing;
71
72 #[test]
73 fn test_durations() {
74 let microsecond = Duration::from_micros(1);
75
76 let t0 = Timing(microsecond * 555);
77 assert_eq!(t0.to_string(), "555µs");
78
79 let t1 = Timing(microsecond * 666_444);
80 assert_eq!(t1.to_string(), "666.44ms");
81
82 let t2 = Timing(microsecond * 777_444_333);
83 assert_eq!(t2.to_string(), "777.44s");
84 }
85}