1 use super::{Duration, Instant};
2 use once_cell::sync::Lazy;
3 #[cfg(not(all(
4     any(target_arch = "wasm32", target_arch = "wasm64"),
5     target_os = "unknown"
6 )))]
7 use std::time;
8 
9 #[cfg(all(
10     any(target_arch = "wasm32", target_arch = "wasm64"),
11     target_os = "unknown"
12 ))]
13 use wasm_bindgen::prelude::*;
14 
15 #[cfg(all(
16     any(target_arch = "wasm32", target_arch = "wasm64"),
17     target_os = "unknown"
18 ))]
19 #[wasm_bindgen]
20 extern "C" {
21     type Date;
22 
23     #[wasm_bindgen(static_method_of = Date)]
now() -> f6424     pub fn now() -> f64;
25 }
26 
27 /// System time
28 #[derive(Debug)]
29 pub struct Clock;
30 
31 /// Alias for `Duration`.
32 pub type UnixTimeStamp = Duration;
33 
34 static CLOCK_OFFSET: Lazy<u64> = Lazy::new(clock_offset);
35 
36 impl Clock {
37     /// Returns the elapsed time since the UNIX epoch
38     #[inline]
now_since_epoch() -> UnixTimeStamp39     pub fn now_since_epoch() -> UnixTimeStamp {
40         let offset = *CLOCK_OFFSET;
41         let unix_ts_now = Instant::now().as_u64().wrapping_sub(offset);
42         Duration::from_u64(unix_ts_now)
43     }
44 
45     /// Returns the elapsed time since the UNIX epoch, based on the latest explicit time update
46     #[inline]
recent_since_epoch() -> UnixTimeStamp47     pub fn recent_since_epoch() -> UnixTimeStamp {
48         let offset = *CLOCK_OFFSET;
49         let unix_ts_now = Instant::recent().as_u64().wrapping_sub(offset);
50         Duration::from_u64(unix_ts_now)
51     }
52 
53     /// Updates the system time - This is completely equivalent to calling Instant::update()
54     #[inline]
update()55     pub fn update() {
56         Instant::update()
57     }
58 }
59 
60 #[cfg(all(
61     any(target_arch = "wasm32", target_arch = "wasm64"),
62     target_os = "unknown"
63 ))]
64 #[inline]
unix_ts() -> u6465 fn unix_ts() -> u64 {
66     let unix_ts_now_sys = (Date::now() / 1000.0).round() as u64;
67     let unix_ts_now = Duration::from_secs(unix_ts_now_sys);
68     unix_ts_now.as_u64()
69 }
70 
71 #[cfg(not(all(
72     any(target_arch = "wasm32", target_arch = "wasm64"),
73     target_os = "unknown"
74 )))]
75 #[inline]
unix_ts() -> u6476 fn unix_ts() -> u64 {
77     let unix_ts_now_sys = time::SystemTime::now()
78         .duration_since(time::UNIX_EPOCH)
79         .expect("The system clock is not properly set");
80     let unix_ts_now = Duration::from(unix_ts_now_sys);
81     unix_ts_now.as_u64()
82 }
83 
clock_offset() -> u6484 fn clock_offset() -> u64 {
85     let unix_ts_now = unix_ts();
86     let instant_now = Instant::now().as_u64();
87     instant_now.wrapping_sub(unix_ts_now)
88 }
89