pub(crate) mod timepriv;
pub trait Unit {
const LABEL: &'static str;
const INVERSE: &'static str;
const S_FACTOR: f64;
fn factor<T: Unit>() -> f64 {
Self::S_FACTOR / T::S_FACTOR
}
}
#[macro_export]
macro_rules! time_unit {
(
$(#[$doc:meta])* $unit:ident,
$label:expr,
$inverse:expr,
$s_factor:expr
) => {
$(#[$doc])*
#[allow(non_camel_case_types)]
#[derive(Clone, Copy, Debug, PartialEq, PartialOrd)]
pub struct $unit;
impl $crate::time::Unit for $unit {
const LABEL: &'static str = $label;
const INVERSE: &'static str = $inverse;
const S_FACTOR: f64 = $s_factor;
}
impl core::ops::Mul<$unit> for f64 {
type Output = $crate::Period<$unit>;
fn mul(self, _other: $unit) -> Self::Output {
$crate::Period::new(self)
}
}
impl core::ops::Mul<$unit> for i32 {
type Output = $crate::Period<$unit>;
fn mul(self, _other: $unit) -> Self::Output {
$crate::Period::new(f64::from(self))
}
}
impl core::ops::Div<$unit> for f64 {
type Output = $crate::Frequency<$unit>;
fn div(self, _other: $unit) -> Self::Output {
$crate::Frequency::new(self)
}
}
impl core::ops::Div<$unit> for i32 {
type Output = $crate::Frequency<$unit>;
fn div(self, _other: $unit) -> Self::Output {
$crate::Frequency::new(f64::from(self))
}
}
impl<L> core::ops::Div<$unit> for $crate::Length<L>
where
L: $crate::length::Unit
{
type Output = $crate::Speed<L, $unit>;
fn div(self, _unit: $unit) -> Self::Output {
$crate::Speed::new(self.quantity)
}
}
};
}
time_unit!(
Gs,
"Gs",
"nHz",
1_000_000_000.0
);
time_unit!(
Ms,
"Ms",
"μHz",
1_000_000.0
);
time_unit!(
Ks,
"Ks",
"mHz",
1_000.0
);
time_unit!(
wk,
"wk",
"/wk",
7.0 * 24.0 * 60.0 * 60.0
);
time_unit!(
d,
"d",
"/d",
24.0 * 60.0 * 60.0
);
time_unit!(
h,
"h",
"/h",
60.0 * 60.0
);
time_unit!(
min,
"min",
"/min",
60.0
);
time_unit!(
s,
"s",
"㎐",
1.0
);
time_unit!(
ds,
"ds",
"daHz",
0.1
);
time_unit!(
ms,
"ms",
"㎑",
0.001
);
time_unit!(
us,
"μs",
"㎒",
0.000_001
);
time_unit!(
ns,
"ns",
"㎓",
0.000_000_001
);
time_unit!(
ps,
"ps",
"㎔",
0.000_000_000_001
);
#[cfg(test)]
mod test {
extern crate alloc;
use super::super::Frequency;
use super::*;
use alloc::{format, string::ToString};
#[test]
fn time_display() {
assert_eq!((23.7 * s).to_string(), "23.7 s");
assert_eq!((3.25 * h).to_string(), "3.25 h");
assert_eq!((50.0 / s).to_string(), "50 ㎐");
assert_eq!((2.0 / d).to_string(), "2 /d");
assert_eq!(format!("{:.1}", 333.3333 / us), "333.3 ㎒");
}
#[test]
fn time_to() {
assert_eq!((4.75 * h).to(), 285.0 * min);
assert_eq!((2.5 * s).to(), 2_500.0 * ms);
assert_eq!((1_000.0 / s).to(), 1.0 / ms);
assert_eq!((300.0 / ms).to(), 0.3 / us);
}
#[test]
fn time_add() {
assert_eq!(3.5 * d + 1.25 * d, 4.75 * d);
assert_eq!(1.0 * wk + 2.1 * wk, 3.1 * wk);
assert_eq!(5.0 / ns + 4.0 / ns, 9.0 / ns);
}
#[test]
fn time_sub() {
assert_eq!(567.8 * us - 123.4 * us, 444.4 * us);
assert_eq!(23.0 / ms - 12.0 / ms, 11.0 / ms);
}
#[test]
fn time_mul() {
assert_eq!((6.5 * ns) * 12.0, 78.0 * ns);
assert_eq!(4.0 * (1.5 * h), 6.0 * h);
assert_eq!(2.5 / ds * 2.0, 5.0 / ds);
}
#[test]
fn time_div() {
assert_eq!(5. / h, Frequency::<h>::new(5.0));
assert_eq!(60.0 / s, Frequency::<s>::new(60.0));
assert_eq!(1.0 / (1.0 * s), 1.0 / s);
assert_eq!(2.0 / (1.0 / min), 2.0 * min);
}
}