es_entity/clock/
global.rs1use chrono::{DateTime, Utc};
2
3use std::sync::OnceLock;
4use std::time::Duration;
5
6use super::{ClockController, ClockHandle, ClockSleep, ClockTimeout};
7
8struct GlobalState {
9 handle: ClockHandle,
10 controller: Option<ClockController>,
11}
12
13static GLOBAL: OnceLock<GlobalState> = OnceLock::new();
14
15pub struct Clock;
17
18impl Clock {
19 pub fn now() -> DateTime<Utc> {
23 Self::handle().now()
24 }
25
26 pub fn today() -> chrono::NaiveDate {
30 Self::handle().today()
31 }
32
33 pub fn sleep(duration: Duration) -> ClockSleep {
35 Self::handle().sleep(duration)
36 }
37
38 pub fn timeout<F: std::future::Future>(duration: Duration, future: F) -> ClockTimeout<F> {
40 Self::handle().timeout(duration, future)
41 }
42
43 pub fn handle() -> &'static ClockHandle {
45 &GLOBAL
46 .get_or_init(|| GlobalState {
47 handle: ClockHandle::realtime(),
48 controller: None,
49 })
50 .handle
51 }
52
53 pub fn install_manual() -> ClockController {
61 if let Some(state) = GLOBAL.get() {
63 return state
64 .controller
65 .clone()
66 .expect("Cannot install manual clock: realtime clock already initialized");
67 }
68
69 let (handle, ctrl) = ClockHandle::manual();
71
72 match GLOBAL.set(GlobalState {
73 handle,
74 controller: Some(ctrl.clone()),
75 }) {
76 Ok(()) => ctrl,
77 Err(_) => {
78 GLOBAL
80 .get()
81 .unwrap()
82 .controller
83 .clone()
84 .expect("Cannot install manual clock: realtime clock already initialized")
85 }
86 }
87 }
88
89 pub fn install_manual_at(start_at: DateTime<Utc>) -> ClockController {
93 if let Some(state) = GLOBAL.get() {
95 return state
96 .controller
97 .clone()
98 .expect("Cannot install manual clock: realtime clock already initialized");
99 }
100
101 let (handle, ctrl) = ClockHandle::manual_at(start_at);
103
104 match GLOBAL.set(GlobalState {
105 handle,
106 controller: Some(ctrl.clone()),
107 }) {
108 Ok(()) => ctrl,
109 Err(_) => {
110 GLOBAL
112 .get()
113 .unwrap()
114 .controller
115 .clone()
116 .expect("Cannot install manual clock: realtime clock already initialized")
117 }
118 }
119 }
120
121 pub fn is_manual() -> bool {
123 GLOBAL
124 .get()
125 .map(|s| s.controller.is_some())
126 .unwrap_or(false)
127 }
128
129 pub fn manual_now() -> Option<DateTime<Utc>> {
136 GLOBAL.get().and_then(|s| s.handle.manual_now())
137 }
138}