use std::time::{SystemTime, UNIX_EPOCH};
pub trait Clock: Send + Sync + 'static {
fn now(&self) -> SystemTime;
fn now_secs(&self) -> u64 {
self.now().duration_since(UNIX_EPOCH).unwrap_or_default().as_secs()
}
fn now_secs_i64(&self) -> i64 {
i64::try_from(self.now_secs()).unwrap_or(0)
}
}
#[derive(Debug, Clone, Default)]
pub struct SystemClock;
impl Clock for SystemClock {
#[inline]
fn now(&self) -> SystemTime {
SystemTime::now()
}
}
#[cfg(any(test, feature = "test-utils"))]
#[derive(Debug, Clone)]
pub struct ManualClock {
current: std::sync::Arc<std::sync::Mutex<SystemTime>>,
}
#[cfg(any(test, feature = "test-utils"))]
impl Default for ManualClock {
fn default() -> Self {
Self::new()
}
}
#[cfg(any(test, feature = "test-utils"))]
impl ManualClock {
#[must_use]
pub fn new() -> Self {
Self {
current: std::sync::Arc::new(std::sync::Mutex::new(
SystemTime::UNIX_EPOCH + std::time::Duration::from_secs(1_000_000),
)),
}
}
pub fn advance(&self, delta: std::time::Duration) {
*self.current.lock().expect("ManualClock mutex poisoned") += delta;
}
pub fn set(&self, t: SystemTime) {
*self.current.lock().expect("ManualClock mutex poisoned") = t;
}
}
#[cfg(any(test, feature = "test-utils"))]
impl Clock for ManualClock {
fn now(&self) -> SystemTime {
*self.current.lock().expect("ManualClock mutex poisoned")
}
}