chronotope / chrono-tz

TimeZone implementations for rust-chrono from the IANA database
Other
229 stars 55 forks source link

Serialize DateTime<Tz> not rfc3339 compliant #126

Closed jcare44 closed 3 months ago

jcare44 commented 1 year ago

There seem to be an issue with the serialize of DateTime<Tz>. Whether it be DateTime<Utc> or DateTime<Local>, serialize seem to always return a string that is compliant with rfc3339 (ending with Z or an offset like +01:00). But with DateTime<Tz>'s serialize, it seem to end (at least in my cases) with the timezone's letters instead (like CEST).

use chrono::{DateTime, Local, Utc};
use chrono_tz::Europe::Paris;
use chrono_tz::Tz;

let d1: DateTime<Utc> = Utc::now();
println!("{}", serde_json::to_string(&d1).unwrap());
// "2023-03-16T10:21:43.519697Z"

let d2: DateTime<Local> = Local::now(); // (My local is also Europe/Paris here)
println!("{}", serde_json::to_string(&d2).unwrap());
// "2023-03-16T11:21:43.520310+01:00"

let d3: DateTime<Tz> = Utc::now().with_timezone(&Paris);
println!("{}", serde_json::to_string(&d3).unwrap());
// "2023-03-16T11:21:43.520494CET"

And it does this even though d3.to_rfc3339() works well.

Did I miss something, or is this a bug?

djc commented 1 year ago

It sure sounds like a bug, though I don't recall the relevant parts of the standards. Would you be able to open a PR to fix this ideally with a bunch of context on what is/isn't allowed in 3339?

polarathene commented 4 months ago

Did I miss something, or is this a bug?

You should find that if you convert the Tz via into() or similar to a:

But yes, RFC 3339 expects to format the IANA TZ to a UTC offset not as the TZ abbreviation (which can be ambiguous, such as with how CST maps to three different UTC offsets).

So that is a bug AFAIK.


EDIT: I thought I had reproduced the issue when I chimed in 🤔 If I did I must have had an outdated version of chrono 🤷‍♂️

Reproduction (confirming is fixed):

$ docker run --rm -it --workdir /example rust:alpine ash
# musl-dev needed for compiling with `cargo run`, while tzdata needed for `TZ` ENV support:
$ apk add musl-dev nano tzdata && cargo init

# Replace with above example wrapped in `fn main() { ... }`
$ nano src/main.rs
$ cargo add serde_json chrono-tz chrono --features chrono/serde

# Working:
$ TZ=Europe/Paris cargo run
"2024-04-06T00:23:19.179698686Z"
# This is `+02:00` instead of `+01:00` as April is DST for Paris:
"2024-03-06T02:23:19.179734183+02:00"
"2024-04-06T02:23:19.179776783+02:00"
pitdicker commented 3 months ago

This was fixed in chrono 0.4.27 with https://github.com/chronotope/chrono/pull/1035.