From 15f81167bceaf86dfb8c59697612f08f66bd52e2 Mon Sep 17 00:00:00 2001 From: Paul Dicker Date: Tue, 6 Jun 2023 16:28:10 +0200 Subject: [PATCH] Correct offset calculation on wasm_bindgen --- src/offset/local/mod.rs | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/src/offset/local/mod.rs b/src/offset/local/mod.rs index 04f9221424..9e7d30335a 100644 --- a/src/offset/local/mod.rs +++ b/src/offset/local/mod.rs @@ -50,15 +50,34 @@ mod inner { not(any(target_os = "emscripten", target_os = "wasi")) ))] mod inner { - use crate::{FixedOffset, LocalResult, NaiveDateTime}; + use crate::{Datelike, FixedOffset, LocalResult, NaiveDateTime, Timelike}; - pub(super) fn offset_from_utc_datetime(_utc: &NaiveDateTime) -> LocalResult { - let offset = js_sys::Date::new_0().get_timezone_offset(); + pub(super) fn offset_from_utc_datetime(utc: &NaiveDateTime) -> LocalResult { + let offset = js_sys::Date::from(utc.and_utc()).get_timezone_offset(); LocalResult::Single(FixedOffset::west_opt((offset as i32) * 60).unwrap()) } pub(super) fn offset_from_local_datetime(local: &NaiveDateTime) -> LocalResult { - offset_from_utc_datetime(local) + let mut year = local.year(); + if year < 100 { + // The API in `js_sys` does not let us create a `Date` with negative years. + // And values for years from `0` to `99` map to the years `1900` to `1999`. + // Shift the value by a multiple of 400 years until it is `>= 100`. + let shift_cycles = (year - 100).div_euclid(400); + year -= shift_cycles * 400; + } + let js_date = js_sys::Date::new_with_year_month_day_hr_min_sec( + year as u32, + local.month0() as i32, + local.day() as i32, + local.hour() as i32, + local.minute() as i32, + local.second() as i32, + // ignore milliseconds, our representation of leap seconds may be problematic + ); + let offset = js_date.get_timezone_offset(); + // We always get a result, even if this time does not exist or is ambiguous. + LocalResult::Single(FixedOffset::west_opt((offset as i32) * 60).unwrap()) } }