1use bstr::ByteSlice;
2
3use crate::{SecondsSinceUnixEpoch, Time};
4
5impl std::fmt::Display for Time {
7 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
8 let mut buf = Vec::with_capacity(Time::MAX.size());
9 self.write_to(&mut buf).expect("write to memory cannot fail");
10 #[allow(unsafe_code)]
12 let raw = unsafe { buf.to_str_unchecked() };
13 f.write_str(raw)
14 }
15}
16
17impl Time {
19 pub fn write_to(&self, out: &mut dyn std::io::Write) -> std::io::Result<()> {
21 const SECONDS_PER_HOUR: u32 = 60 * 60;
22 let offset = self.offset.unsigned_abs();
23 let hours = offset / SECONDS_PER_HOUR;
24 let minutes = (offset - (hours * SECONDS_PER_HOUR)) / 60;
25
26 if hours > 99 {
27 return Err(std::io::Error::new(
28 std::io::ErrorKind::Other,
29 "Cannot represent offsets larger than +-9900",
30 ));
31 }
32
33 let mut itoa = itoa::Buffer::new();
34 out.write_all(itoa.format(self.seconds).as_bytes())?;
35 out.write_all(b" ")?;
36 out.write_all(if self.offset < 0 { b"-" } else { b"+" })?;
37
38 const ZERO: &[u8; 1] = b"0";
39
40 if hours < 10 {
41 out.write_all(ZERO)?;
42 }
43 out.write_all(itoa.format(hours).as_bytes())?;
44
45 if minutes < 10 {
46 out.write_all(ZERO)?;
47 }
48 out.write_all(itoa.format(minutes).as_bytes()).map(|_| ())
49 }
50
51 pub const fn size(&self) -> usize {
53 (if self.seconds >= 1_000_000_000_000_000_000 {
54 19
55 } else if self.seconds >= 100_000_000_000_000_000 {
56 18
57 } else if self.seconds >= 10_000_000_000_000_000 {
58 17
59 } else if self.seconds >= 1_000_000_000_000_000 {
60 16
61 } else if self.seconds >= 100_000_000_000_000 {
62 15
63 } else if self.seconds >= 10_000_000_000_000 {
64 14
65 } else if self.seconds >= 1_000_000_000_000 {
66 13
67 } else if self.seconds >= 100_000_000_000 {
68 12
69 } else if self.seconds >= 10_000_000_000 {
70 11
71 } else if self.seconds >= 1_000_000_000 {
72 10
73 } else if self.seconds >= 100_000_000 {
74 9
75 } else if self.seconds >= 10_000_000 {
76 8
77 } else if self.seconds >= 1_000_000 {
78 7
79 } else if self.seconds >= 100_000 {
80 6
81 } else if self.seconds >= 10_000 {
82 5
83 } else if self.seconds >= 1_000 {
84 4
85 } else if self.seconds >= 100 {
86 3
87 } else if self.seconds >= 10 {
88 2
89 } else if self.seconds >= 0 {
90 1
91 } else if self.seconds >= -10 {
93 2
94 } else if self.seconds >= -100 {
95 3
96 } else if self.seconds >= -1_000 {
97 4
98 } else if self.seconds >= -10_000 {
99 5
100 } else if self.seconds >= -100_000 {
101 6
102 } else if self.seconds >= -1_000_000 {
103 7
104 } else if self.seconds >= -10_000_000 {
105 8
106 } else if self.seconds >= -100_000_000 {
107 9
108 } else if self.seconds >= -1_000_000_000 {
109 10
110 } else if self.seconds >= -10_000_000_000 {
111 11
112 } else if self.seconds >= -100_000_000_000 {
113 12
114 } else if self.seconds >= -1_000_000_000_000 {
115 13
116 } else if self.seconds >= -10_000_000_000_000 {
117 14
118 } else if self.seconds >= -100_000_000_000_000 {
119 15
120 } else if self.seconds >= -1_000_000_000_000_000 {
121 16
122 } else if self.seconds >= -10_000_000_000_000_000 {
123 17
124 } else if self.seconds >= -100_000_000_000_000_000 {
125 18
126 } else if self.seconds >= -1_000_000_000_000_000_000 {
127 19
128 } else {
129 20
130 }) + 2 + 2 + 2 }
132
133 pub const MAX: Time = Time {
136 seconds: SecondsSinceUnixEpoch::MAX,
137 offset: 99 * 60 * 60 + 59 * 60 + 59,
138 };
139}