use crate::epoch::SECONDS_PER_DAY;
#[derive(Debug, Clone)]
pub struct UserDefinedEpoch {
pub epoch_in_parent: f64,
pub seconds: f64,
pub days: f64,
pub clock_day: i32,
pub clock_hour: i32,
pub clock_minute: i32,
pub clock_second: f64,
}
impl UserDefinedEpoch {
pub fn new(epoch_in_parent: f64) -> Self {
Self {
epoch_in_parent,
seconds: 0.0,
days: 0.0,
clock_day: 0,
clock_hour: 0,
clock_minute: 0,
clock_second: 0.0,
}
}
pub fn update(&mut self, parent_seconds: f64) {
self.seconds = parent_seconds - self.epoch_in_parent;
self.days = self.seconds / SECONDS_PER_DAY;
self.clock_update();
}
fn clock_update(&mut self) {
let mut scratch = self.seconds.rem_euclid(SECONDS_PER_DAY);
self.clock_day = self.seconds.div_euclid(SECONDS_PER_DAY) as i32;
self.clock_hour = scratch.div_euclid(3600.0) as i32;
scratch = scratch.rem_euclid(3600.0);
self.clock_minute = scratch.div_euclid(60.0) as i32;
self.clock_second = scratch.rem_euclid(60.0);
let clock_resolution = 1e-6;
if self.clock_second > 60.0 - clock_resolution {
self.clock_second = 0.0;
self.clock_minute += 1;
if self.clock_minute == 60 {
self.clock_minute = 0;
self.clock_hour += 1;
if self.clock_hour == 24 {
self.clock_hour = 0;
self.clock_day += 1;
}
}
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn ude_basic() {
let mut ude = UserDefinedEpoch::new(1000.0);
assert_eq!(ude.seconds, 0.0);
ude.update(1100.0);
assert!((ude.seconds - 100.0).abs() < 1e-15);
assert!((ude.days - 100.0 / 86400.0).abs() < 1e-15);
}
#[test]
fn ude_clock_decomposition() {
let mut ude = UserDefinedEpoch::new(0.0);
let secs = 86400.0 + 7200.0 + 180.0 + 4.5;
ude.update(secs);
assert_eq!(ude.clock_day, 1);
assert_eq!(ude.clock_hour, 2);
assert_eq!(ude.clock_minute, 3);
assert!((ude.clock_second - 4.5).abs() < 1e-10);
}
#[test]
fn ude_zero_epoch() {
let mut ude = UserDefinedEpoch::new(0.0);
ude.update(3600.0);
assert!((ude.seconds - 3600.0).abs() < 1e-15);
assert_eq!(ude.clock_hour, 1);
assert_eq!(ude.clock_minute, 0);
}
#[test]
fn ude_negative_time() {
let mut ude = UserDefinedEpoch::new(1000.0);
ude.update(500.0);
assert!((ude.seconds - (-500.0)).abs() < 1e-15);
}
}