rapport_temporal/
clock.rs1use chrono::Utc;
4use parking_lot::RwLock;
5use std::sync::Arc;
6
7use crate::{date::Date, time::Instant};
8
9#[derive(Debug, Clone, derive_more::Display)]
10pub enum Clock {
11 #[display("system time")]
12 System,
13 #[display("{_0}")]
14 Fake(FakeClock),
15}
16
17impl Clock {
18 #[must_use]
19 pub fn now(&self) -> Instant {
20 match self {
21 Clock::System => Instant::from_utc_datetime(Utc::now()),
22 Clock::Fake(provider) => provider.now(),
23 }
24 }
25
26 #[must_use]
27 pub fn today(&self) -> Date {
28 self.now().into_date()
29 }
30}
31
32#[derive(Debug, Clone, derive_more::Display)]
35#[display("fake time (for testing), current time: {}", time.read().to_string())]
36pub struct FakeClock {
37 time: Arc<RwLock<Instant>>,
38}
39
40impl Default for FakeClock {
41 fn default() -> Self {
42 Self::new(Instant::from_utc_datetime(Utc::now()))
44 }
45}
46
47impl FakeClock {
48 #[must_use]
49 pub fn new(time: Instant) -> Self {
50 Self {
51 time: Arc::new(RwLock::new(time)),
52 }
53 }
54
55 pub fn add_days(&self, value: u32) {
56 let now = self.now();
57 let add_seconds = value * 24 * 60 * 60;
58 let added = Instant {
59 seconds: now.seconds.saturating_add(add_seconds.into()),
60 nanos: now.nanos,
61 };
62 self.set_time(added);
63 }
64
65 pub fn set_time(&self, time: Instant) {
66 *self.time.write() = time;
67 }
68
69 #[must_use]
70 pub fn now(&self) -> Instant {
71 *self.time.read()
72 }
73}
74
75impl From<FakeClock> for Clock {
76 fn from(value: FakeClock) -> Self {
77 Self::Fake(value)
78 }
79}
80
81impl From<&FakeClock> for Clock {
82 fn from(value: &FakeClock) -> Self {
83 value.clone().into()
84 }
85}