use chrono::{DateTime, Duration, Utc};
use std::sync::{Arc, Mutex};
#[derive(Clone, Debug)]
pub struct Clock {
inner: ClockInner,
}
impl Clock {
pub fn new() -> Self {
Self {
inner: ClockInner::Wall,
}
}
pub fn new_fake(start: DateTime<Utc>) -> Self {
Self {
inner: ClockInner::Fake(FakeClock::new(start)),
}
}
pub fn now(&self) -> DateTime<Utc> {
match &self.inner {
ClockInner::Wall => Utc::now(),
ClockInner::Fake(f) => f.now(),
}
}
pub fn is_fake(&self) -> bool {
match &self.inner {
ClockInner::Wall => false,
ClockInner::Fake(_) => true,
}
}
pub fn advance(&mut self, duration: Duration) -> DateTime<Utc> {
match &self.inner {
ClockInner::Wall => panic!("Attempted to advance system clock"),
ClockInner::Fake(f) => f.advance(duration),
}
}
}
impl Default for Clock {
fn default() -> Self {
Self::new()
}
}
#[derive(Clone, Debug)]
enum ClockInner {
Wall,
Fake(FakeClock),
}
#[derive(Clone, Debug)]
struct FakeClock {
now: Arc<Mutex<DateTime<Utc>>>,
}
impl FakeClock {
pub(crate) fn new(start: DateTime<Utc>) -> Self {
Self {
now: Arc::new(Mutex::new(start)),
}
}
pub(crate) fn now(&self) -> DateTime<Utc> {
*self.now.lock().unwrap()
}
pub(crate) fn advance(&self, duration: Duration) -> DateTime<Utc> {
let mut v = self.now.lock().unwrap();
*v = *v + duration;
*v
}
}