Can't parse datetime string

Sure I am being really dumb here
Why does the following datetime str fail to parse ?

fn main() {
let datetime_str = "2023-12-02T00:00:00.000 UTC";

let datetime = match DateTime::parse_from_str(datetime_str, "%Y-%m-%dT%H:%M:%S%.3f Z") {
    Ok(datetime) => datetime,
    Err(_) => panic!("Failed to parse datetime: {}", datetime_str),
};

}


https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=d4a8ed6901bf9a1cb0847ad9e1c095d7

Thanks

The error message, which is being thrown away by the Err(_) =>, says "input contains invalid characters", and it happens regardless of the order that datetime_str and your formatting string are passed to DateTime::parse_from_str().

Are you sure that's the correct format string? What about starting from something like DateTime::parse_from_str("2023", "%Y") and incrementally adding bits to both the format string and your input until the code errrors out?

hmm got it passing with

fn main() {
    let datetime_str = "2023-12-02T00:00:00.000 UTC";

    //DateTime::parse_from_str
    
    // Parse datetime string
    let datetime = match Utc.datetime_from_str(&datetime_str, "%Y-%m-%dT%H:%M:%S%.3f UTC") {
        Ok(datetime) => datetime,
        Err(err) => {
            panic!("Failed to parse datetime: {}: {}", datetime_str, err);
        }
    };
    
    println!("datetime: {}", datetime);
}

but

Utc.datetime_from_str is depreciated

using

DateTime::parse_from_str gives

Failed to parse datetime: 2023-12-02T00:00:00.000 UTC: input is not enough for unique date and time

The %Z formatter does not populate the offset because you can't reliably match a time zone name to an UTC offset which chrono uses. Could you by any means change your datetime string to use the UTC offset rather than the time zone name?

use chrono::DateTime;

fn main() {
    // let datetime_str = "2023-12-02T00:00:00.000 UTC";
    let datetime_str = "2023-12-02T00:00:00.000+0000";

    match DateTime::parse_from_str(datetime_str, "%Y-%m-%dT%H:%M:%S%.3f%z") {
        Ok(datetime) => datetime,
        Err(e) => panic!("Failed to parse datetime: {e}"),
    };
}

Playground.

Thanks . Unfortunately it comes from a third party service that I can't break at the moment.
I do know in reality all the datetimes it returns are Utc so I suspect I need to strip the Utc off and read as a NaiveDatetime or something like that.

If that's true parsing to a NaiveDateTime sounds reasonable to me. You can match the trailing UTC with %Z, chrono will ignore it internally anyways:

use chrono::{NaiveDateTime, TimeZone, Utc};

fn main() {
    // let datetime_str = "2023-12-02T00:00:00.000 UTC";
    let datetime_str = "2023-12-02T00:00:00.000 UTC";

    // Parse datetime string
    let datetime = match NaiveDateTime::parse_from_str(datetime_str, "%Y-%m-%dT%H:%M:%S%.3f %Z") {
        Ok(datetime) => datetime,
        Err(e) => panic!("Failed to parse datetime: {e}"),
    };

    let datetime = Utc.from_utc_datetime(&datetime);
}

Playground.

3 Likes