use serde::{Deserialize, Serialize};
use log::error;
use crate::message::Message;
#[derive(Clone, Copy, Serialize, Deserialize, Debug, Eq, PartialEq, Ord, PartialOrd)]
pub struct Time {
pub sec: i32,
pub nanosec: u32,
}
impl Message for Time {}
impl Time {
pub const ZERO: Time = Time { sec: 0, nanosec: 0 };
pub const DUMMY: Time = Time {
sec: 1234567890,
nanosec: 1234567890,
};
pub fn now() -> Self {
match chrono::Utc::now().timestamp_nanos_opt() {
None => {
error!("Timestamp out of range.");
Time::ZERO }
Some(negative) if negative < 0 => {
error!("Timestamp out of range (negative).");
Time::ZERO }
Some(non_negative) => Self::from_nanos(non_negative as u64),
}
}
fn from_nanos(nanos_since_epoch: u64) -> Self {
Self {
sec: (nanos_since_epoch / 1_000_000_000) as i32,
nanosec: (nanos_since_epoch % 1_000_000_000) as u32,
}
}
}
#[derive(Clone, Serialize, Deserialize, Debug)]
pub struct Duration {
pub sec: i32, pub nanosec: u32,
}
impl Message for Duration {}
impl Duration {
pub const fn from_secs(sec: i32) -> Self {
Self { sec, nanosec: 0 }
}
pub const fn from_millis(millis: i64) -> Self {
let nanos = millis * 1_000_000; Self::from_nanos(nanos)
}
pub const fn from_nanos(nanos: i64) -> Self {
let quot = nanos / 1_000_000_000;
let rem = nanos % 1_000_000_000;
if rem >= 0 {
if quot > (i32::MAX as i64) {
Duration {
sec: i32::MAX,
nanosec: u32::MAX,
}
} else if quot <= (i32::MIN as i64) {
Duration {
sec: i32::MIN,
nanosec: 0,
}
} else {
Duration {
sec: quot as i32,
nanosec: rem as u32,
}
}
} else {
if quot <= (i32::MIN as i64) {
Duration {
sec: i32::MIN,
nanosec: 0,
}
} else {
Duration {
sec: (quot + 1) as i32,
nanosec: (1_000_000_000 + rem) as u32,
}
}
}
}
pub fn to_nanos(&self) -> i64 {
let s = self.sec as i64;
let ns = self.nanosec as i64;
1_000_000_000 * s + ns
}
}