1pub(crate) mod timepriv;
30
31pub trait Unit {
33 const LABEL: &'static str;
35
36 const INVERSE: &'static str;
38
39 const S_FACTOR: f64;
41
42 fn factor<T: Unit>() -> f64 {
44 Self::S_FACTOR / T::S_FACTOR
45 }
46}
47
48#[macro_export]
73macro_rules! time_unit {
74 (
75 $(#[$doc:meta])* $unit:ident,
76 $label:expr,
77 $inverse:expr,
78 $s_factor:expr
79 ) => {
80 $(#[$doc])*
81 #[allow(non_camel_case_types)]
82 #[derive(Clone, Copy, Debug, PartialEq, PartialOrd)]
83 pub struct $unit;
84
85 impl $crate::time::Unit for $unit {
86 const LABEL: &'static str = $label;
87 const INVERSE: &'static str = $inverse;
88 const S_FACTOR: f64 = $s_factor;
89 }
90
91 impl core::ops::Mul<$unit> for f64 {
93 type Output = $crate::Period<$unit>;
94 fn mul(self, _other: $unit) -> Self::Output {
95 $crate::Period::new(self)
96 }
97 }
98
99 impl core::ops::Mul<$unit> for i32 {
101 type Output = $crate::Period<$unit>;
102 fn mul(self, _other: $unit) -> Self::Output {
103 $crate::Period::new(f64::from(self))
104 }
105 }
106
107 impl core::ops::Div<$unit> for f64 {
109 type Output = $crate::Frequency<$unit>;
110 fn div(self, _other: $unit) -> Self::Output {
111 $crate::Frequency::new(self)
112 }
113 }
114
115 impl core::ops::Div<$unit> for i32 {
117 type Output = $crate::Frequency<$unit>;
118 fn div(self, _other: $unit) -> Self::Output {
119 $crate::Frequency::new(f64::from(self))
120 }
121 }
122
123 impl<L> core::ops::Div<$unit> for $crate::Length<L>
125 where
126 L: $crate::length::Unit
127 {
128 type Output = $crate::Speed<L, $unit>;
129 fn div(self, _unit: $unit) -> Self::Output {
130 $crate::Speed::new(self.quantity)
131 }
132 }
133 };
134}
135
136time_unit!(
137 Gs,
139 "Gs",
140 "nHz",
141 1_000_000_000.0
142);
143
144time_unit!(
145 Ms,
147 "Ms",
148 "μHz",
149 1_000_000.0
150);
151
152time_unit!(
153 Ks,
155 "Ks",
156 "mHz",
157 1_000.0
158);
159
160time_unit!(
161 wk,
163 "wk",
164 "/wk",
165 7.0 * 24.0 * 60.0 * 60.0
166);
167
168time_unit!(
169 d,
171 "d",
172 "/d",
173 24.0 * 60.0 * 60.0
174);
175
176time_unit!(
177 h,
179 "h",
180 "/h",
181 60.0 * 60.0
182);
183
184time_unit!(
185 min,
187 "min",
188 "/min",
189 60.0
190);
191
192time_unit!(
193 s,
195 "s",
196 "㎐",
197 1.0
198);
199
200time_unit!(
201 ds,
203 "ds",
204 "daHz",
205 0.1
206);
207
208time_unit!(
209 ms,
211 "ms",
212 "㎑",
213 0.001
214);
215
216time_unit!(
217 us,
219 "μs",
220 "㎒",
221 0.000_001
222);
223
224time_unit!(
225 ns,
227 "ns",
228 "㎓",
229 0.000_000_001
230);
231
232time_unit!(
233 ps,
235 "ps",
236 "㎔",
237 0.000_000_000_001
238);
239
240#[cfg(test)]
241mod test {
242 extern crate alloc;
243
244 use super::super::Frequency;
245 use super::*;
246 use alloc::{format, string::ToString};
247
248 #[test]
249 fn time_display() {
250 assert_eq!((23.7 * s).to_string(), "23.7 s");
251 assert_eq!((3.25 * h).to_string(), "3.25 h");
252 assert_eq!((50.0 / s).to_string(), "50 ㎐");
253 assert_eq!((2.0 / d).to_string(), "2 /d");
254 assert_eq!(format!("{:.1}", 333.3333 / us), "333.3 ㎒");
255 }
256
257 #[test]
258 fn time_to() {
259 assert_eq!((4.75 * h).to(), 285.0 * min);
260 assert_eq!((2.5 * s).to(), 2_500.0 * ms);
261 assert_eq!((1_000.0 / s).to(), 1.0 / ms);
262 assert_eq!((300.0 / ms).to(), 0.3 / us);
263 }
264
265 #[test]
266 fn time_add() {
267 assert_eq!(3.5 * d + 1.25 * d, 4.75 * d);
268 assert_eq!(1.0 * wk + 2.1 * wk, 3.1 * wk);
269 assert_eq!(5.0 / ns + 4.0 / ns, 9.0 / ns);
270 }
271
272 #[test]
273 fn time_sub() {
274 assert_eq!(567.8 * us - 123.4 * us, 444.4 * us);
275 assert_eq!(23.0 / ms - 12.0 / ms, 11.0 / ms);
276 }
277
278 #[test]
279 fn time_mul() {
280 assert_eq!((6.5 * ns) * 12.0, 78.0 * ns);
281 assert_eq!(4.0 * (1.5 * h), 6.0 * h);
282 assert_eq!(2.5 / ds * 2.0, 5.0 / ds);
283 }
284
285 #[test]
286 fn time_div() {
287 assert_eq!(5. / h, Frequency::<h>::new(5.0));
288 assert_eq!(60.0 / s, Frequency::<s>::new(60.0));
289 assert_eq!(1.0 / (1.0 * s), 1.0 / s);
290 assert_eq!(2.0 / (1.0 / min), 2.0 * min);
291 }
292}