use std::ops::{Add, Sub};
use std::sync::Arc;
use std::time::Duration;
use tokio::time::Instant;
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub struct Timestamp(Instant);
impl Timestamp {
pub fn duration_since(&self, earlier: Timestamp) -> Duration {
self.0
.checked_duration_since(earlier.0)
.unwrap_or_else(|| Duration::from_secs(0))
}
pub fn now() -> Self {
Timestamp(Instant::now())
}
}
impl Add<Duration> for Timestamp {
type Output = Timestamp;
fn add(self, duration: Duration) -> Self::Output {
Timestamp(self.0 + duration)
}
}
impl Sub<Duration> for Timestamp {
type Output = Timestamp;
fn sub(self, duration: Duration) -> Self::Output {
Timestamp(self.0 - duration)
}
}
pub trait Time: Send + Sync {
fn now(&self) -> Timestamp;
}
impl<T: Time> Time for Arc<T>
where
T: Time,
{
fn now(&self) -> Timestamp {
<T as Time>::now(self)
}
}
impl<T: Time> Time for Box<T>
where
T: Time,
{
fn now(&self) -> Timestamp {
<T as Time>::now(self)
}
}
impl<T: Time> Time for &T
where
T: Time,
{
fn now(&self) -> Timestamp {
<T as Time>::now(self)
}
}
#[derive(Debug, Clone, Copy)]
pub struct TokioTime {
base_instant: Instant,
base_timestamp: Timestamp,
}
impl TokioTime {
pub fn new() -> Self {
let base_instant = tokio::time::Instant::now();
let base_timestamp = Timestamp::now();
Self {
base_instant,
base_timestamp,
}
}
}
impl Default for TokioTime {
fn default() -> Self {
Self::new()
}
}
impl Time for TokioTime {
fn now(&self) -> Timestamp {
let now = Instant::now();
let elapsed = now.duration_since(self.base_instant);
self.base_timestamp + elapsed
}
}