1use chrono::{DateTime, Utc};
2use parking_lot::Mutex;
3use std::time::{Duration, Instant};
4
5pub trait Clock {
6 fn utc_now(&self) -> DateTime<Utc>;
7 fn now(&self) -> Instant;
8}
9
10pub struct TestClock(Mutex<TestClockState>);
11
12struct TestClockState {
13 now: Instant,
14 utc_now: DateTime<Utc>,
15}
16
17impl TestClock {
18 pub fn new() -> Self {
19 const START_TIME: &str = "2025-07-01T23:59:58-00:00";
20 let utc_now = DateTime::parse_from_rfc3339(START_TIME).unwrap().to_utc();
21 Self(Mutex::new(TestClockState {
22 now: Instant::now(),
23 utc_now,
24 }))
25 }
26
27 pub fn set_utc_now(&self, now: DateTime<Utc>) {
28 let mut state = self.0.lock();
29 state.utc_now = now;
30 }
31
32 pub fn advance(&self, duration: Duration) {
33 let mut state = self.0.lock();
34 state.now += duration;
35 state.utc_now += duration;
36 }
37}
38
39impl Clock for TestClock {
40 fn utc_now(&self) -> DateTime<Utc> {
41 self.0.lock().utc_now
42 }
43
44 fn now(&self) -> Instant {
45 self.0.lock().now
46 }
47}