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?
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