diff --git a/Cargo.toml b/Cargo.toml index 50ea6fd..fef04db 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,6 +20,14 @@ cfg-if = "1.0.0" thiserror = { version = "1.0.30", optional = true } nom = { version = "7.1.0", optional = true } +[target.'cfg(not(target_family = "wasm"))'.dependencies] +time = { version = "0.3.7", features = ["macros"] } + +[target.'cfg(target_family = "wasm")'.dependencies] +js-sys = { version = "0.3.64", optional = true } +time = { version = "0.3.7", features = ["macros", "wasm-bindgen"] } +wasm-bindgen = "0.2.87" + [target.'cfg(windows)'.dependencies] windows-sys = { version = "0.32.0", features = ["Win32_System_Time", "Win32_Foundation"], optional = true } @@ -31,7 +39,7 @@ serde = { version = "1.0.136", features = ["derive"] } [features] default = ["db"] -system = ["windows-sys", "thiserror", "db"] +system = ["windows-sys", "js-sys", "thiserror", "db"] posix-tz = ["nom", "thiserror", "db"] db = [] diff --git a/src/binary_search.rs b/src/binary_search.rs index f17d72b..10de82f 100644 --- a/src/binary_search.rs +++ b/src/binary_search.rs @@ -41,19 +41,23 @@ pub fn binary_search Ordering>(start: usize, end: usize, cmp: F) } } -#[test] -fn test_binary_search() { - assert_eq!(binary_search(0, 8, |x| x.cmp(&6)), Some(6)); - assert_eq!(binary_search(0, 5000, |x| x.cmp(&1337)), Some(1337)); - assert_eq!(binary_search(0, 5000, |x| x.cmp(&9000)), None); - assert_eq!(binary_search(30, 50, |x| x.cmp(&42)), Some(42)); - assert_eq!(binary_search(300, 500, |x| x.cmp(&42)), None); - assert_eq!( - binary_search(0, 500, |x| if x < 42 { - Ordering::Less - } else { - Ordering::Greater - }), - None - ); -} +#[cfg(test)] +mod tests { + #[test] + fn test_binary_search() { + assert_eq!(super::binary_search(0, 8, |x| x.cmp(&6)), Some(6)); + assert_eq!(super::binary_search(0, 5000, |x| x.cmp(&1337)), Some(1337)); + assert_eq!(super::binary_search(0, 5000, |x| x.cmp(&9000)), None); + assert_eq!(super::binary_search(30, 50, |x| x.cmp(&42)), Some(42)); + assert_eq!(super::binary_search(300, 500, |x| x.cmp(&42)), None); + assert_eq!( + super::binary_search(0, 500, |x| if x < 42 { + super::Ordering::Less + } else { + super::Ordering::Greater + }), + None + ); + } + +} \ No newline at end of file diff --git a/src/lib.rs b/src/lib.rs index d77cd6c..5a01231 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -60,7 +60,7 @@ pub trait PrimitiveDateTimeExt: sealing::PrimitiveDateTimeExt { /// /// * `tz`: the target timezone. /// - /// returns: OffsetResult + /// returns: `OffsetResult` fn assume_timezone(&self, tz: &T) -> OffsetResult; /// Creates a new OffsetDateTime with the proper offset in the given timezone. diff --git a/src/system.rs b/src/system.rs index ceabcbc..4945c6b 100644 --- a/src/system.rs +++ b/src/system.rs @@ -26,10 +26,19 @@ // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +//! Support for getting time zone information from the target system. +//! +//! Currently only supported for Windows, Unix, and WASM targets. + use crate::timezones::get_by_name; use crate::Tz; use thiserror::Error; +#[cfg(target_family = "wasm")] +use js_sys::{ Intl, Reflect, Array, Object }; +#[cfg(target_family = "wasm")] +use wasm_bindgen::JsValue; + #[derive(Debug, Error)] pub enum Error { /// An IO error has occurred. @@ -52,8 +61,18 @@ pub enum Error { /// The timezone doesn't exist in the crate's database. #[error("unknown timezone name")] Unknown, + + /// The target platform is not supported. Windows, Unix, and WASM targets are the only supported for the system feature at this moment. + #[error("unsupported platform")] + Unsupported, } +/// Gets the current timezone from the system. +/// +/// Currently only supported for Windows, Unix, and WASM targets. +/// +/// # Errors +/// Returns an [Error](enum@Error) if the timezone cannot be determined. pub fn get_timezone() -> Result<&'static Tz, Error> { cfg_if::cfg_if! { if #[cfg(unix)] { @@ -67,7 +86,7 @@ pub fn get_timezone() -> Result<&'static Tz, Error> { } else { Err(Error::Undetermined) } - } else { + } else if #[cfg(windows)] { unsafe { use windows_sys::Win32::System::Time::GetDynamicTimeZoneInformation; use windows_sys::Win32::System::Time::DYNAMIC_TIME_ZONE_INFORMATION; @@ -89,6 +108,19 @@ pub fn get_timezone() -> Result<&'static Tz, Error> { Ok(tz) } } + } else if #[cfg(target_family = "wasm")] { + let options = Intl::DateTimeFormat::new(&Array::new(), &Object::new()) + .resolved_options(); + + let tz = Reflect::get(&options, &JsValue::from("timeZone")) + .map_err(|_| Error::Undetermined)? + .as_string() + .ok_or(Error::Unicode)?; + + let tz = get_by_name(&tz).ok_or(Error::Unknown)?; + Ok(tz) + } else { + Err(Error::Unsupported) } } }