use crate::platform::prelude::*;
use core::{
ops::Sub,
sync::atomic::{self, AtomicPtr},
};
pub use time::{Duration, OffsetDateTime as DateTime};
pub trait Clock: 'static {
fn now(&self) -> Duration;
fn date_now(&self) -> DateTime;
}
static CLOCK: AtomicPtr<Box<dyn Clock>> = AtomicPtr::new(core::ptr::null_mut());
pub fn register_clock(clock: impl Clock) {
let clock: Box<dyn Clock> = Box::new(clock);
let clock = Box::new(clock);
if !CLOCK.load(atomic::Ordering::SeqCst).is_null() {
panic!("The clock has already been registered");
}
CLOCK.store(Box::into_raw(clock), atomic::Ordering::SeqCst);
}
#[derive(Copy, Clone, PartialOrd, PartialEq, Ord, Eq, Debug)]
pub struct Instant(Duration);
impl Instant {
pub fn now() -> Self {
let clock = CLOCK.load(atomic::Ordering::SeqCst);
if clock.is_null() {
panic!("No clock registered");
}
let clock = unsafe { &*clock };
Instant(clock.now())
}
}
impl Sub<Duration> for Instant {
type Output = Instant;
fn sub(self, rhs: Duration) -> Instant {
Self(self.0 - rhs)
}
}
impl Sub for Instant {
type Output = Duration;
fn sub(self, rhs: Instant) -> Duration {
self.0 - rhs.0
}
}
pub fn utc_now() -> DateTime {
let clock = CLOCK.load(atomic::Ordering::SeqCst);
if clock.is_null() {
panic!("No clock registered");
}
let clock = unsafe { &*clock };
clock.date_now()
}
pub fn to_local(date_time: DateTime) -> DateTime {
date_time
}