Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Chrono can't parse a date from iso8601 #163

Closed
iddm opened this issue Jun 23, 2017 · 6 comments
Closed

Chrono can't parse a date from iso8601 #163

iddm opened this issue Jun 23, 2017 · 6 comments

Comments

@iddm
Copy link

iddm commented Jun 23, 2017

Some server sends me the date time in the json:

"creationTime": "2017-06-22 13:32:16Z",

But I can't parse it neither trough Datetime nor NaiveDateTime. However, if I change the space between the date and the time to T as in 2017-06-22T13:32:16Z it parses okay.

I could not find any information does this conform iso8601 or not, different sources say different answers, iso8601. If it is iso8601 so the chrono must be able to parse it.

@quodlibetor
Copy link
Contributor

ISO 8601 (and RFC 3339) both require the T.

The readme contains examples for parsing a datetime that includes a space, if you'd like.

@iddm
Copy link
Author

iddm commented Jun 23, 2017

@quodlibetor I don't parse it manually, I use serde for this. If I did that manually, I would have everything okay of course. I have also found the resources you told but some other resources also treat a datetime stamp without T as correct, however, I have not seen anything like that before today. I have told the api writer of the service I use to add T to the timestamp.

@quodlibetor
Copy link
Contributor

quodlibetor commented Jun 23, 2017

In that case if you need to use it you can write my_custom_deserializer module (like we have for timestamps) that parses your format, if the service you're interacting with doesn't support it.

Something like the following (untested) code:

pub mod custom_deserialize {
    use std::fmt;
    use serde::de;

    use chrono::NaiveDateTime;

    struct NaiveDateTimeFromMyFormatVisitor;

    pub fn deserialize<'de, D>(d: D) -> Result<NaiveDateTime, D::Error>
        where D: de::Deserializer<'de>
    {
        Ok(try!(d.deserialize_str(NaiveDateTimeFromMyFormatVisitor)))
    }

    impl<'de> de::Visitor<'de> for NaiveDateTimeFromSecondsVisitor {
        type Value = NaiveDateTime;

        fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result
        {
            write!(formatter, "a datetime string")
        }

        fn visit_str<E>(self, value: &str) -> Result<NaiveDateTime, E>
            where E: de::Error
        {
            DateTime::parse_from_str(value, "%Y-%m-%d %H:%M:%S%z")
                .map_err(|e| E::custom(format!("Parse error {} for {}", e, value)))
        }
    }
}

Should allow you to use serde's #[serde(deserialize_with = "custom_deserialize::deserialize")] attribute in your struct.

@iddm
Copy link
Author

iddm commented Jun 23, 2017

@quodlibetor thanks a lot, I will try that if the resource refuse to support the correct version of time stamp.

@iddm
Copy link
Author

iddm commented Jun 24, 2017

@quodlibetor the service api author gave me this link which says the T may be omitted. What do you think?

@quodlibetor
Copy link
Contributor

Ha, the specific text in the note in wikipedia is:

4.3.2 NOTE: By mutual agreement of the partners in information interchange, the character [T] may be omitted in applications where there is no risk of confusing a date and time of day representation with others defined in this International Standard.

so, if you agree that the T may be omitted then the format can still be considered ISO-8601 compliant 😄 It still wouldn't be RFC 3339 compliant, though.

Adding the ability to accept the space would require an attempted parse and a fallback. That seems like an unacceptable hidden performance hit for default behavior.

I'll investigate alternate parsing techniques, but it won't be super fast, our current code is pretty... specific.

If you want to accept strings in the format that you are currently receiving I'd recommend going with the alternate deserialization I described in a previous comment.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants