Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add native support for WASM targets #14

Merged
merged 12 commits into from
Jul 22, 2023
10 changes: 9 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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 }

Expand All @@ -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 = []

Expand Down
36 changes: 20 additions & 16 deletions src/binary_search.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,19 +41,23 @@ pub fn binary_search<F: Fn(usize) -> 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
);
}

}
2 changes: 1 addition & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ pub trait PrimitiveDateTimeExt: sealing::PrimitiveDateTimeExt {
///
/// * `tz`: the target timezone.
///
/// returns: OffsetResult<OffsetDateTime>
/// returns: `OffsetResult<OffsetDateTime>`
fn assume_timezone<T: TimeZone>(&self, tz: &T) -> OffsetResult<OffsetDateTime>;

/// Creates a new OffsetDateTime with the proper offset in the given timezone.
Expand Down
34 changes: 33 additions & 1 deletion src/system.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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)] {
Expand All @@ -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;
Expand All @@ -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)
}
}
}
Expand Down