rustrust-chrono

How to catch panic error from DelayedFormat?


I have this script:

use chrono::{NaiveDateTime};

fn func(fmt: &str) -> Result<(), String>{
    let date_str = "2020-01-01 00:00";
    let dt = NaiveDateTime::parse_from_str(date_str, "%Y-%m-%d %H:%M").unwrap();
    let formatted = format!("{}", dt.format(fmt));
    println!("formatted: {formatted}");
    Ok(())
}

fn main() {
    match func("%Y") {
        Err(_) => println!("errored"),
        Ok(_) => println!("worked"),
    }
}

It runs fine, but if I change it to func("%z"), then format!("{}", dt.format(fmt)) panics.

How can I "catch" this panic, and raise an informative error message if a "wrong" fmt was passed?


Solution

  • I think your question is an XY problem. You shouldn't ask how to catch the panic, but how to avoid it.

    The Display trait already has the option to produce a proper Result, it just gets converted to a panic by format!().

    The solution is to not use format!(). Instead, use write!(), which gives you the error instead of converting it to a panic:

    use std::fmt::Write;
    
    use chrono::NaiveDateTime;
    
    fn func(fmt: &str) -> Result<String, std::fmt::Error> {
        let date_str = "2020-01-01 00:00";
        let dt = NaiveDateTime::parse_from_str(date_str, "%Y-%m-%d %H:%M").unwrap();
    
        let mut formatted = String::new();
        write!(formatted, "{}", dt.format(fmt))?;
        Ok(formatted)
    }
    
    fn main() {
        match func("%Y") {
            Err(err) => println!("errored: {}", err),
            Ok(msg) => println!("worked: {}", msg),
        }
    
        match func("%z") {
            Err(err) => println!("errored: {}", err),
            Ok(msg) => println!("worked: {}", msg),
        }
    }
    
    worked: 2020
    errored: an error occurred when formatting an argument