use crate::units::{Distance, Energy, Length, Power, Speed};
use crate::Magnitude;
#[derive(Clone, Copy, Debug)]
pub struct Time {
pub m: Magnitude,
}
impl Time {
#[inline]
pub const fn new(m: Magnitude) -> Self {
Self { m }
}
#[inline]
pub const fn m(&self) -> Magnitude {
self.m
}
}
impl Time {
pub fn from_distance_speed(d: Distance, s: Speed) -> Self {
Self::new(d.m / s.m)
}
pub fn from_speed_distance(s: Speed, d: Distance) -> Self {
Time::from_distance_speed(d, s)
}
pub fn calc_speed(&self, d: Distance) -> Speed {
Speed::new(d.m / self.m)
}
#[inline]
pub fn calc_distance(&self, s: Speed) -> Distance {
Length::new(self.m * s.m)
}
#[inline]
pub fn from_energy_power(e: Energy, p: Power) -> Self {
Self::new(e.m / p.m)
}
#[inline]
pub fn from_power_energy(p: Power, e: Energy) -> Self {
Self::from_energy_power(e, p)
}
#[inline]
pub fn calc_power(&self, e: Energy) -> Power {
Power::new(e.m / self.m)
}
#[inline]
pub fn calc_energy(&self, p: Power) -> Time {
Time::new(self.m * p.m)
}
}
impl Time {
pub const JULIAN_YEAR: Self = Time::new(31_557_600.);
pub const FULL_MOON_CYCLE: Self = Time::new(35578174.777056);
pub const DRACONIC_YEAR: Self = Time::new(29947974.5562912);
pub const LUNAR_YEAR: Self = Time::new(30617314.848);
}
impl Time {
scalar_methods![Time, qa = min, Qa = minutes, f = 60., fu = "60", bu = s];
scalar_methods![Time, qa = h, Qa = hours, f = 3600., fu = "3600", bu = s];
scalar_methods![Time, qa = d, Qa = days, f = 86_400., fu = "86400", bu = s];
scalar_methods![
Time,
qa = w,
Qa = weeks,
f = 604_800.,
fu = "604800",
bu = s
];
scalar_methods![
Time,
qa = y,
Qa = years,
f = 31_536e3,
fu = "365",
bu = "days"
];
scalar_methods![
Time,
qa = jy,
Qa = julian_years,
qu = "`jy`",
Qu = "`julian years`",
f = Time::JULIAN_YEAR.m,
fu = "365.25",
bu = "days"
];
}
impl_scalar_methods![Time, s, seconds];
#[cfg(test)]
mod tests {
use {super::*, float_eq::assert_float_eq};
#[test]
fn time_formulas() {
let time = Time::from_distance_speed(Length::new(300.), Speed::new(12.));
assert_float_eq!(25., time.m, r2nd <= Magnitude::EPSILON);
assert_float_eq!(
time.m,
Time::from_speed_distance(Speed::new(12.), Length::new(300.)).m,
r2nd <= Magnitude::EPSILON
);
assert_float_eq!(
300.,
time.calc_distance(Speed::new(12.)).m,
r2nd <= Magnitude::EPSILON
);
assert_float_eq!(
12.,
time.calc_speed(Length::new(300.)).m,
r2nd <= Magnitude::EPSILON
);
let time = Time::from_energy_power(Energy::in_kJ(144.), Power::new(800.));
assert_float_eq!(Time::in_min(3.).m, time.m, r2nd <= Magnitude::EPSILON);
assert_float_eq!(
time.m,
Time::from_power_energy(Power::new(800.), Energy::in_kJ(144.)).m,
r2nd <= Magnitude::EPSILON,
);
assert_float_eq!(
Energy::in_kJ(144.).m,
time.calc_energy(Power::new(800.)).m,
r2nd <= Magnitude::EPSILON
);
assert_float_eq!(
Power::new(800.).m,
time.calc_power(Energy::in_kJ(144.)).m,
r2nd <= Magnitude::EPSILON
);
}
#[test]
fn time_constants() {
assert_float_eq!(
365.25,
Time::JULIAN_YEAR.as_days(),
r2nd <= Magnitude::EPSILON
);
assert_float_eq!(
411.78443029,
Time::FULL_MOON_CYCLE.as_days(),
r2nd <= Magnitude::EPSILON
);
assert_float_eq!(
346.620075883,
Time::DRACONIC_YEAR.as_days(),
r2nd <= Magnitude::EPSILON
);
assert_float_eq!(
354.36707,
Time::LUNAR_YEAR.as_days(),
r2nd <= Magnitude::EPSILON
);
}
#[test]
fn time_non_si() {
assert_float_eq!(60., Time::in_min(1.).m, r2nd <= Magnitude::EPSILON);
assert_float_eq!(3600., Time::in_h(1.).m, r2nd <= Magnitude::EPSILON);
assert_float_eq!(86_400., Time::in_d(1.).m, r2nd <= Magnitude::EPSILON);
assert_float_eq!(604_800., Time::in_w(1.).m, r2nd <= Magnitude::EPSILON);
assert_float_eq!(31_536e3, Time::in_y(1.).m, r2nd <= Magnitude::EPSILON);
assert_float_eq!(
Time::JULIAN_YEAR.m,
Time::in_jy(1.).m,
r2nd <= Magnitude::EPSILON
);
}
}