time
time copied to clipboard
Sub-millisecond component inaccuracy in OffsetDateTime conversion from js_sys::Date
When generating an OffsetDateTime
from a js_sys::Date
, there are cases where the sub-millisecond components are not set to zero. This behavior is unexpected and can lead to inaccuracies in the resulting OffsetDateTime
.
Steps to Reproduce
- Use the following code to reproduce the issue:
let millis = 1699083911579i64; // 2023-11-04T07:45:11.579Z
let js_date = js_sys::Date::new(&JsValue::from_f64(millis as f64));
let datetime = OffsetDateTime::from(js_date);
println!("{}", datetime);
// => 2023-11-04 7:45:11.579000064 +00:00:00
Reason for Considering It a Bug
The precision of js_sys::Date
is limited to milliseconds. Therefore, when converting it to an OffsetDateTime
, we expect the sub-millisecond components to be set to zero for consistency and accuracy.
Cause
https://github.com/time-rs/time/blob/72f03e05073621f713dead88f16c227187afd6f9/time/src/date_time.rs#L1226-L1233
The issue stems from the conversion process of milliseconds to nanoseconds. It appears that the code converts milliseconds to nanoseconds using f64
, and subsequently converts it to i128
, which can introduce inaccuracies and prevent sub-millisecond components from being zeroed out.
Proposed Solution
To address this issue, consider converting milliseconds to i128 first and then perform the conversion to nanoseconds. This approach should maintain accuracy and ensure that sub-millisecond components are set to zero.
Additional Information
I encountered this issue while using OffsetDateTime::now_utc()
in a WASM environment.
Without even looking into this, I am confident that the multiplication magnifies the inherent error of representing decimal values in floating point numbers. I'm happy to accept your proposed solution as a PR, as I'm sure it'll fix the issue.