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