0

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?

ignoring_gravity
  • 6,677
  • 4
  • 32
  • 65
  • Does this answer your question? [Suppress panic output in Rust when using panic::catch\_unwind](https://stackoverflow.com/questions/35559267/suppress-panic-output-in-rust-when-using-paniccatch-unwind) – Ömer Erden Feb 11 '23 at 11:38
  • 1
    @ÖmerErden I think this is an XY problem. Yes, you could catch the panic, but the method should not cause a panic in the first place. Will create an answer. – Finomnis Feb 11 '23 at 14:26
  • 1
    @Finomnis better approach, anyway I'll keep the dupe link for the APIs that have no implementation alternative to panicking one. – Ömer Erden Feb 11 '23 at 14:45

1 Answers1

2

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
Finomnis
  • 18,094
  • 1
  • 20
  • 27