use std::time::{Duration, SystemTime, UNIX_EPOCH};
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub struct Time {
pub sec: u64,
pub nsec: u32,
}
impl Time {
pub fn new(sec: u64, nsec: u32) -> Self {
let mut time = Self { sec, nsec };
time.normalize();
time
}
pub fn now() -> Self {
let now = SystemTime::now()
.duration_since(UNIX_EPOCH)
.expect("System time before Unix epoch");
Self::from(now)
}
pub fn from_duration(duration: Duration) -> Self {
Self::new(duration.as_secs(), duration.subsec_nanos())
}
pub fn to_duration(&self) -> Duration {
Duration::new(self.sec, self.nsec)
}
fn normalize(&mut self) {
if self.nsec >= 1_000_000_000 {
self.sec += u64::from(self.nsec) / 1_000_000_000;
self.nsec %= 1_000_000_000;
}
}
pub fn add(&self, duration: Duration) -> Self {
let duration_since_epoch = self.to_duration();
let new_duration = duration_since_epoch + duration;
Self::from_duration(new_duration)
}
pub fn sub(&self, duration: Duration) -> Self {
let duration_since_epoch = self.to_duration();
let new_duration = duration_since_epoch
.checked_sub(duration)
.unwrap_or_else(|| Duration::new(0, 0));
Self::from_duration(new_duration)
}
}
impl From<Duration> for Time {
fn from(duration: Duration) -> Self {
Self::from_duration(duration)
}
}
impl From<SystemTime> for Time {
fn from(time: SystemTime) -> Self {
let duration = time
.duration_since(UNIX_EPOCH)
.expect("System time before Unix epoch");
Self::from(duration)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub struct ZenobufDuration {
pub sec: i32,
pub nsec: i32,
}
impl ZenobufDuration {
pub fn new(sec: i32, nsec: i32) -> Self {
let mut duration = Self { sec, nsec };
duration.normalize();
duration
}
pub fn from_std(duration: Duration) -> Self {
Self::new(duration.as_secs() as i32, duration.subsec_nanos() as i32)
}
pub fn to_std(&self) -> Duration {
Duration::new(self.sec as u64, self.nsec as u32)
}
fn normalize(&mut self) {
if self.nsec >= 1_000_000_000 {
self.sec += self.nsec / 1_000_000_000;
self.nsec %= 1_000_000_000;
} else if self.nsec < 0 {
let sec_adj = (-self.nsec / 1_000_000_000) + 1;
self.sec -= sec_adj;
self.nsec += sec_adj * 1_000_000_000;
}
}
}
impl From<Duration> for ZenobufDuration {
fn from(duration: Duration) -> Self {
Self::from_std(duration)
}
}
impl From<ZenobufDuration> for Duration {
fn from(duration: ZenobufDuration) -> Self {
duration.to_std()
}
}