coarsetime/
clock.rs

1#[cfg(not(all(
2    any(target_arch = "wasm32", target_arch = "wasm64"),
3    target_os = "unknown"
4)))]
5use std::time;
6
7use std::sync::atomic::{AtomicU64, Ordering};
8
9use super::Duration;
10
11static RECENT: AtomicU64 = AtomicU64::new(0);
12
13#[cfg(all(
14    any(target_arch = "wasm32", target_arch = "wasm64"),
15    target_os = "unknown"
16))]
17mod js_imports {
18    use wasm_bindgen::prelude::*;
19
20    #[wasm_bindgen]
21    extern "C" {
22        pub type Date;
23
24        #[wasm_bindgen(static_method_of = Date)]
25        pub fn now() -> f64;
26    }
27}
28
29/// System time
30#[derive(Debug)]
31pub struct Clock;
32
33/// Alias for `Duration`.
34pub type UnixTimeStamp = Duration;
35
36impl Clock {
37    /// Returns the elapsed time since the UNIX epoch
38    #[inline]
39    pub fn now_since_epoch() -> UnixTimeStamp {
40        Duration::from_u64(unix_ts())
41    }
42
43    /// Returns the elapsed time since the UNIX epoch, based on the latest
44    /// explicit time update
45    #[inline]
46    pub fn recent_since_epoch() -> UnixTimeStamp {
47        Duration::from_u64(RECENT.load(Ordering::Relaxed))
48    }
49
50    /// Updates the cached system time.
51    ///
52    /// This function should be called frequently, for example in an event loop
53    /// or using an `Updater` task.
54    #[inline]
55    pub fn update() {
56        let now = unix_ts();
57        RECENT.store(now, Ordering::Relaxed)
58    }
59
60    /// Sets the cached system time to the specified timestamp.
61    /// This function is intended for testing purposes only.
62    /// It should not be used in production code.
63    pub fn set_recent_since_epoch(recent: UnixTimeStamp) {
64        RECENT.store(recent.as_u64(), Ordering::Relaxed)
65    }
66}
67
68#[cfg(all(
69    any(target_arch = "wasm32", target_arch = "wasm64"),
70    target_os = "unknown"
71))]
72#[inline]
73fn unix_ts() -> u64 {
74    let unix_ts_now_sys = (js_imports::Date::now() / 1000.0).round() as u64;
75    let unix_ts_now = Duration::from_secs(unix_ts_now_sys);
76    unix_ts_now.as_u64()
77}
78
79#[cfg(not(all(
80    any(target_arch = "wasm32", target_arch = "wasm64"),
81    target_os = "unknown"
82)))]
83#[inline]
84fn unix_ts() -> u64 {
85    let unix_ts_now_sys = time::SystemTime::now()
86        .duration_since(time::UNIX_EPOCH)
87        .expect("The system clock is not properly set");
88    let unix_ts_now = Duration::from(unix_ts_now_sys);
89    unix_ts_now.as_u64()
90}