Skip to main content

embedded_date_time/
time.rs

1use core::fmt;
2
3/// A simple time of a day.
4#[derive(PartialEq, Eq, Hash, PartialOrd, Ord, Copy, Clone)]
5pub struct Time {
6    /// Hour of the day [0-23].
7    pub hour: u8,
8
9    /// Minute of the hour [0-59].
10    pub minute: u8,
11
12    /// Second of the minute [0-60].
13    ///
14    /// A value of 60 might occur on a leap second.
15    pub second: u8,
16}
17
18impl Time {
19    /// Create a new Time from hours, minutes and seconds.
20    ///
21    /// No checks will be performed to validate the time.
22    #[must_use]
23    pub fn new(hour: u8, minute: u8, second: u8) -> Self {
24        Self {
25            hour,
26            minute,
27            second,
28        }
29    }
30
31    /// Create a new Time from hours, minutes and seconds.
32    ///
33    /// Returns None if the hour, minute or second is invalid.
34    ///
35    /// Seconds are permitted to be 60 on a leap second.
36    #[must_use]
37    pub fn new_checked(hour: u8, minute: u8, second: u8) -> Option<Self> {
38        let result = Self::new(hour, minute, second);
39        result.is_valid().then_some(result)
40    }
41
42    /// Determine whether the time is a valid combination of hours, minutes and seconds.
43    ///
44    /// Seconds are permitted to be 60 on a leap second.
45    #[must_use]
46    pub fn is_valid(self) -> bool {
47        self.hour <= 23 && self.minute <= 59 && self.second <= 60
48    }
49}
50
51impl fmt::Debug for Time {
52    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
53        fmt::Display::fmt(&self, f)
54    }
55}
56
57impl fmt::Display for Time {
58    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
59        write!(f, "{:02}:{:02}:{:02}", self.hour, self.minute, self.second)
60    }
61}
62
63#[cfg(feature = "defmt")]
64impl defmt::Format for Time {
65    fn format(&self, fmt: defmt::Formatter<'_>) {
66        defmt::write!(
67            fmt,
68            "{:02}:{:02}:{:02}",
69            self.hour,
70            self.minute,
71            self.second
72        );
73    }
74}
75
76#[cfg(feature = "ufmt")]
77impl ufmt::uDebug for Time {
78    fn fmt<W>(&self, fmt: &mut ufmt::Formatter<'_, W>) -> Result<(), W::Error>
79    where
80        W: ufmt::uWrite + ?Sized,
81    {
82        ufmt::uDisplay::fmt(&self, fmt)
83    }
84}
85
86#[cfg(feature = "ufmt")]
87impl ufmt::uDisplay for Time {
88    fn fmt<W>(&self, fmt: &mut ufmt::Formatter<'_, W>) -> Result<(), W::Error>
89    where
90        W: ufmt::uWrite + ?Sized,
91    {
92        use ufmt::uwrite;
93
94        let Self {
95            hour,
96            minute,
97            second,
98        } = *self;
99
100        if hour < 10 {
101            uwrite!(fmt, "0{}:", hour)?;
102        } else {
103            uwrite!(fmt, "{}:", hour)?;
104        }
105
106        if minute < 10 {
107            uwrite!(fmt, "0{}:", minute)?;
108        } else {
109            uwrite!(fmt, "{}:", minute)?;
110        }
111
112        if second < 10 {
113            uwrite!(fmt, "0{}", second)?;
114        } else {
115            uwrite!(fmt, "{}", second)?;
116        }
117
118        Ok(())
119    }
120}