1use crate::{Clock, Timer};
2use futures::future::BoxFuture;
3use jiff::tz::TimeZone;
4use jiff::Timestamp;
5use std::time::Duration;
6
7pub struct WallClock;
9
10impl Clock for WallClock {
11 fn now(&self) -> Timestamp {
12 Timestamp::now()
13 }
14}
15
16pub fn system_tz() -> TimeZone {
25 TimeZone::system()
26}
27
28pub struct TokioTimer;
30
31impl Timer for TokioTimer {
32 fn sleep(&self, dur: Duration) -> BoxFuture<'static, ()> {
33 Box::pin(async move {
34 tokio::time::sleep(dur).await;
35 })
36 }
37
38 fn next_tick(&self) -> BoxFuture<'static, ()> {
39 Box::pin(async {
40 tokio::task::yield_now().await;
41 })
42 }
43}
44
45#[cfg(test)]
46mod tests {
47 use super::*;
48 use crate::Clock as ClockTrait;
49 use crate::Timer as TimerTrait;
50 use std::sync::Arc;
51 use std::time::Instant;
52
53 fn assert_send_sync<T: Send + Sync>() {}
54
55 #[test]
56 fn wall_clock_and_tokio_timer_are_send_sync() {
57 assert_send_sync::<WallClock>();
58 assert_send_sync::<TokioTimer>();
59 }
60
61 #[test]
62 fn now_is_recent() {
63 let before = Timestamp::now();
64 let clock = WallClock;
65 let t = clock.now();
66 let after = Timestamp::now();
67 assert!(t >= before - jiff::SignedDuration::from_secs(1));
68 assert!(t <= after + jiff::SignedDuration::from_secs(1));
69 }
70
71 #[test]
72 fn now_unix_millis_positive_and_recent() {
73 let before_ms = Timestamp::now().as_millisecond();
74 let clock = WallClock;
75 let ms = clock.now_unix_millis();
76 let after_ms = Timestamp::now().as_millisecond();
77 assert!(ms > 0, "unix millis must be positive");
78 assert!(ms >= before_ms - 100, "must be >= before sample");
79 assert!(ms <= after_ms + 100, "must be <= after sample");
80 }
81
82 #[tokio::test]
83 async fn tokio_timer_sleep_completes() {
84 let timer = TokioTimer;
85 let start = Instant::now();
86 timer.sleep(Duration::from_millis(50)).await;
87 let elapsed = start.elapsed();
88 assert!(elapsed.as_millis() >= 45, "sleep must take at least 45ms");
89 assert!(elapsed.as_millis() < 500, "sleep must not take more than 500ms");
90 }
91
92 #[tokio::test]
93 async fn tokio_timer_next_tick_completes_immediately() {
94 let timer = TokioTimer;
95 let start = Instant::now();
96 timer.next_tick().await;
97 assert!(start.elapsed().as_millis() < 100);
98 }
99
100 #[test]
101 fn wall_clock_arc_dyn_dispatch() {
102 let c: Arc<dyn ClockTrait> = Arc::new(WallClock);
103 let _ = c.now();
104 }
105
106 #[test]
107 fn tokio_timer_arc_dyn_dispatch() {
108 let t: Arc<dyn TimerTrait> = Arc::new(TokioTimer);
109 let _ = t.sleep(Duration::ZERO);
110 }
111}