1use crate::{SecondsSinceUnixEpoch, Time};
2
3impl std::fmt::Display for Time {
5 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
6 let mut buf = Vec::with_capacity(Time::MAX.size());
7 self.write_to(&mut buf).expect("write to memory cannot fail");
8 let raw = std::str::from_utf8(&buf).expect("time serializes as valid UTF-8");
12 f.write_str(raw)
13 }
14}
15
16impl Time {
18 pub fn write_to(&self, out: &mut dyn std::io::Write) -> std::io::Result<()> {
20 const SECONDS_PER_HOUR: u32 = 60 * 60;
21 let offset = self.offset.unsigned_abs();
22 let hours = offset / SECONDS_PER_HOUR;
23 let minutes = (offset - (hours * SECONDS_PER_HOUR)) / 60;
24
25 if hours > 99 {
26 return Err(std::io::Error::other("Cannot represent offsets larger than +-9900"));
27 }
28
29 let mut itoa = itoa::Buffer::new();
30 out.write_all(itoa.format(self.seconds).as_bytes())?;
31 out.write_all(b" ")?;
32 out.write_all(if self.offset < 0 { b"-" } else { b"+" })?;
33
34 const ZERO: &[u8; 1] = b"0";
35
36 if hours < 10 {
37 out.write_all(ZERO)?;
38 }
39 out.write_all(itoa.format(hours).as_bytes())?;
40
41 if minutes < 10 {
42 out.write_all(ZERO)?;
43 }
44 out.write_all(itoa.format(minutes).as_bytes()).map(|_| ())
45 }
46
47 pub const fn size(&self) -> usize {
49 let is_negative = self.seconds < 0;
50 Self::count_positive_digits(self.seconds.unsigned_abs()) + is_negative as usize + 6
51 }
53
54 const fn count_positive_digits(n: u64) -> usize {
56 const POW10: [u64; 20] = [
58 1,
59 10,
60 100,
61 1_000,
62 10_000,
63 100_000,
64 1_000_000,
65 10_000_000,
66 100_000_000,
67 1_000_000_000,
68 10_000_000_000,
69 100_000_000_000,
70 1_000_000_000_000,
71 10_000_000_000_000,
72 100_000_000_000_000,
73 1_000_000_000_000_000,
74 10_000_000_000_000_000,
75 100_000_000_000_000_000,
76 1_000_000_000_000_000_000,
77 10_000_000_000_000_000_000,
78 ];
79
80 let mut digits = 1;
82 while digits < 20 && n >= POW10[digits] {
83 digits += 1;
84 }
85 digits
86 }
87
88 pub const MAX: Time = Time {
91 seconds: SecondsSinceUnixEpoch::MAX,
92 offset: 99 * 60 * 60 + 59 * 60 + 59,
93 };
94}