DateTime.with_timezone() seems not working with chrono::offset::Local in wasm32
Closed this issue · 7 comments
Here is a simple test for native x86:
fn main() {
let dt = chrono::DateTime::parse_from_rfc3339("2020-04-07T14:07:52+00:00").unwrap();
println!("dt: {}", dt);
println!("dt: {}", dt.with_timezone(&chrono::Local));
}
When I run it in my local timezone (UTC+2) it correctly prints:
dt: 2020-04-07 14:07:52 +00:00
dt: 2020-04-07 16:07:52 +02:00
But in a wasm project, this code:
log!(d);
log!(chrono::Local::now());
log!(d.with_timezone(&chrono::FixedOffset::east(3600)));
log!(d.with_timezone(&chrono::Local));
prints in Firefox:
2020-04-07T14:07:15+00:00
2020-04-10T15:36:23.396+02:00
2020-04-07T15:07:15+01:00
2020-04-07T14:07:15+00:00
You can see that with FixedOffset
I get correct date, but not with Local
.
Is this in a web browser or some other runtime? What runtime in particular is it?
@ip1981 let me know if my attached branch fixes the problem for you. I'm not terribly familiar with the wasm ecosystem so I need to expend some work to get a meaningful test for it, but it seems like it might work.
Is this in a web browser or some other runtime? What runtime in particular is it?
That's in Firefox.
@ip1981 let me know if my attached branch fixes the problem for you. I'm not terribly familiar with the wasm ecosystem so I need to expend some work to get a meaningful test for it, but it seems like it might work.
Yes, it works. I tested the PR with a small change (see my comment over there). And I used similar code as a workaround.
This works for creating a Local
datetime from a Utc
one, but not the other way around.
This:
Local.ymd(2020, 7, 26).and_hms(21, 22, 54);
// or alternately
let naive_date_time = NaiveDateTime::with_ymd(2020, 7, 26).and_hms(21, 22, 54);
Local.from_local_datetime(&naive_date_time).earliest();
still gives "+00:00" offset.
So the use-case of displaying a UTC time in local timezone (e.g. receiving a universal datetime from a server and rendering in browser) is supported, but taking a local datetime and converting to UTC (e.g. reading from a form input and sending to server) is still busted.
This seems to be a currently viable workaround:
// `offset` seems equivalent to how `Local` *should* behave
let offset = Local::now().offset().to_owned();
offset.ymd(2020, 7, 26).and_hms(21, 22, 54);
// or alternately
let naive_date_time = NaiveDateTime::with_ymd(2020, 7, 26).and_hms(21, 22, 54);
offset.from_local_datetime(&naive_date_time).earliest();
but the extra step of constantly using now
is not ideal.
@EndilWayfare I just ran into this as well but was able to solve it by enabling chrono's wasmbind
feature:
[target.'cfg(not(target_arch = "wasm32"))'.dependencies.chrono]
version = "0.4.19"
[target.'cfg(target_arch = "wasm32")'.dependencies.chrono]
version = "0.4.19"
features = ["wasmbind"]
See here for why this is required: https://docs.rs/chrono/0.4.19/src/chrono/offset/local.rs.html#150-169
If you're not using emscripten then I believe that wasmbind
and the wasm-bindgen ecosystem is the best bet.