Idiomatic way to convert from NaiveDate to DateTime<Local>

Help me out, please. What I've come up with is a mess.

From NaiveDateTime is easy, but without the time part, not so much.

I want to just hardcode the time part (to midnight, or whatever).

To convert a chrono::NaiveDate to a chrono::NaiveDateTime with a time of midnight, use and_time and pass a time of midnight.

To convert the result to a DateTime<Local>, you can use and_local_timezone. You’ll need to decide what do do in cases where the result is ambiguous or nonexistant.

pub fn to_local_datetime(date: NaiveDate) -> DateTime<Local> {
    let datetime = date.and_time(NaiveTime::default());
    match datetime.and_local_timezone(Local) {
        MappedLocalTime::Single(dt) => dt,
        MappedLocalTime::Ambiguous(dt0, dt1) => todo!(),
        MappedLocalTime::None => panic!("invalid date/time")
    }
}
3 Likes

Ok - but that is very verbose indeed!

If you just want to choose one of the two times when there is a fold, and panic when there is a gap, then you can use:

NaiveDateTime::new(date, NaiveTime::default())
    .and_local_timezone(Local)
    .earliest()
    .unwrap()
1 Like

Using the NaiveDate::and_time method also makes things slightly shorter:

date.and_time(NaiveTime::default())
    .and_local_timezone(Local)
    .earliest()
    .unwrap()

Updated my original code above to use this instead. You could also use a named constant to make this a bit more readable:

const MIDNIGHT: NaiveTime = NaiveTime::from_hms(0, 0, 0);

fn to_datetime(date: NaiveDate) -> Option<DateTime<Local>> {
    date.and_time(MIDNIGHT).and_local_timezone(Local).earliest()
}
3 Likes