use crate::{Clock, Timer};
use futures::channel::oneshot;
use futures::future::BoxFuture;
use jiff::tz::TimeZone;
use jiff::Timestamp;
use std::time::Duration;
use wasm_bindgen::JsCast;
pub struct WasmClock;
impl Clock for WasmClock {
fn now(&self) -> Timestamp {
let ms = js_sys::Date::now(); Timestamp::from_millisecond(ms as i64).unwrap_or(Timestamp::UNIX_EPOCH)
}
}
pub fn browser_local_tz() -> TimeZone {
use js_sys::{Array, Intl, Object, Reflect};
use wasm_bindgen::JsValue;
let fmt = Intl::DateTimeFormat::new(&Array::new(), &Object::new());
let resolved = fmt.resolved_options();
Reflect::get(&resolved, &JsValue::from_str("timeZone"))
.ok()
.and_then(|v| v.as_string())
.and_then(|s| TimeZone::get(&s).ok())
.unwrap_or(TimeZone::UTC)
}
pub struct WasmTimer;
impl Timer for WasmTimer {
fn sleep(&self, dur: Duration) -> BoxFuture<'static, ()> {
let ms = dur.as_millis().min(i32::MAX as u128) as i32;
let (tx, rx) = oneshot::channel::<()>();
let closure = wasm_bindgen::closure::Closure::once(move || {
let _ = tx.send(());
});
if let Some(win) = web_sys::window() {
let _ = win.set_timeout_with_callback_and_timeout_and_arguments_0(
closure.as_ref().unchecked_ref(),
ms,
);
}
closure.forget();
Box::pin(async move {
let _ = rx.await;
})
}
fn next_tick(&self) -> BoxFuture<'static, ()> {
self.sleep(Duration::ZERO)
}
}