Skip to main content

workflow_core/
time.rs

1//!
2//! `time` module provides re-export of WASM32-compatible `Instant` and provides
3//! platform neutral implementations for [`unixtime_as_millis_u128()`] and
4//! [`unixtime_as_millis_f64()`].
5//!
6
7use cfg_if::cfg_if;
8
9/// re-export of [`instant`] crate supporting native and WASM implementations
10pub use web_time::*;
11
12/// Number of milliseconds in one second.
13pub const SECONDS: u64 = 1000;
14/// Number of milliseconds in one minute.
15pub const MINUTES: u64 = SECONDS * 60;
16/// Number of milliseconds in one hour.
17pub const HOURS: u64 = MINUTES * 60;
18/// Number of milliseconds in one day.
19pub const DAYS: u64 = HOURS * 24;
20
21/// Selects how unix timestamps are rendered to locale strings.
22pub enum TimeFormat {
23    /// 24-hour clock format (`%Y-%m-%d %H:%M:%S`).
24    Time24,
25    /// 12-hour clock format with AM/PM (`%Y-%m-%d %I:%M:%S %p`).
26    Time12,
27    /// The platform/system locale's default date-time representation.
28    Locale,
29    /// A custom `chrono`-style format string.
30    Custom(String),
31}
32
33cfg_if! {
34    if #[cfg(target_arch = "wasm32")] {
35        use js_sys::{Date,Intl,Reflect};
36        use wasm_bindgen::prelude::JsValue;
37
38        /// Returns the current unix time in milliseconds as a `u128`.
39        #[inline(always)]
40        pub fn unixtime_as_millis_u128() -> u128 {
41            Date::now() as u128
42        }
43
44        /// Returns the current unix time in milliseconds as an `f64`.
45        #[inline(always)]
46        pub fn unixtime_as_millis_f64() -> f64 {
47            Date::now()
48        }
49
50        /// Returns the current unix time in milliseconds as a `u64`.
51        #[inline(always)]
52        pub fn unixtime_as_millis_u64() -> u64 {
53            Date::now() as u64
54        }
55
56        /// Formats a unix time in milliseconds as a human-readable locale string.
57        #[inline(always)]
58        pub fn unixtime_to_locale_string(unixtime : u64) -> String {
59            let date = Date::new(&JsValue::from(unixtime as f64));
60            date.to_locale_string(default_locale().as_str(), &JsValue::UNDEFINED).as_string().unwrap()
61        }
62
63        fn default_locale() -> String {
64            static mut LOCALE: Option<String> = None;
65            let locale_ptr = &raw mut LOCALE;
66            unsafe {
67                (*locale_ptr).get_or_insert_with(|| {
68                    let date_time_format = Intl::DateTimeFormat::default();
69                    let resolved_options = date_time_format.resolved_options();
70                    let locale = Reflect::get(&resolved_options, &JsValue::from("locale")).expect("Intl::DateTimeFormat().resolvedOptions().locale is not defined");
71                    locale.as_string().expect("Intl::DateTimeFormat().resolvedOptions().locale()")
72                }).clone()
73            }
74        }
75
76        /// Sets the desired time format used by [`unixtime_to_locale_string`].
77        /// On WASM the argument is ignored and the browser's locale is used instead.
78        pub fn init_desired_time_format(_time_format : TimeFormat) {
79            // time format is ignored in WASM and
80            // the browser's locale is used instead
81        }
82
83    } else {
84        use chrono::{Local, TimeZone};
85
86        /// Returns the current unix time in milliseconds as a `u128`.
87        #[inline(always)]
88        pub fn unixtime_as_millis_u128() -> u128 {
89            SystemTime::now().duration_since(SystemTime::UNIX_EPOCH).expect("unixtime_as_millis_u64").as_millis()
90        }
91
92        /// Returns the current unix time in milliseconds as an `f64`.
93        #[inline(always)]
94        pub fn unixtime_as_millis_f64() -> f64 {
95            SystemTime::now().duration_since(SystemTime::UNIX_EPOCH).expect("unixtime_as_millis_u64").as_millis() as f64
96        }
97
98        /// Returns the current unix time in milliseconds as a `u64`.
99        #[inline(always)]
100        pub fn unixtime_as_millis_u64() -> u64 {
101            SystemTime::now().duration_since(SystemTime::UNIX_EPOCH).expect("unixtime_as_millis_u64").as_millis() as u64
102        }
103
104        static mut TIME_FORMAT: Option<String> = None;
105
106        #[inline(always)]
107        fn time_format() -> &'static str {
108            let time_format_ptr = &raw mut TIME_FORMAT;
109            unsafe {
110                (*time_format_ptr).get_or_insert_with(|| {
111                    "%Y-%m-%d %H:%M:%S".to_string()
112                }).as_str()
113            }
114        }
115
116        /// Sets the [`TimeFormat`] used by [`unixtime_to_locale_string`] for
117        /// subsequent native timestamp formatting.
118        pub fn init_desired_time_format(time_format : TimeFormat) {
119            unsafe {
120                match time_format {
121                    TimeFormat::Time24 => {
122                        TIME_FORMAT = Some("%Y-%m-%d %H:%M:%S".to_string());
123                    },
124                    TimeFormat::Time12 => {
125                        TIME_FORMAT = Some("%Y-%m-%d %I:%M:%S %p".to_string());
126                    },
127                    TimeFormat::Locale => {
128                        TIME_FORMAT = Some("%c".to_string());
129                    },
130                    TimeFormat::Custom(format) => {
131                        TIME_FORMAT = Some(format);
132                    }
133                }
134            }
135        }
136
137        /// Formats a unix time in milliseconds as a local-time string using the
138        /// format configured via [`init_desired_time_format`].
139        #[inline(always)]
140        pub fn unixtime_to_locale_string(unixtime : u64) -> String {
141            let local = Local.timestamp_millis_opt(unixtime as i64).unwrap();
142            local.format(time_format()).to_string()
143        }
144    }
145}
146
147/*
148#[cfg(test)]
149mod tests {
150    use super::*;
151
152    #[test]
153    fn test_unixtime_to_locale_string() {
154        let now = unixtime_as_millis_u64();
155        let locale_string = unixtime_to_locale_string(now);
156        println!("locale_string: {}", locale_string);
157    }
158}
159*/