Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using clap's #[derive(Parser)], how can I accept a std::time::Duration?

Tags:

rust

clap

I want to accept a std::time::Duration on a command line. I'm using clap with #[derive(Parser)] to generate the parameter parser. Is there any way I can directly accept an input, rather than accepting a number and doing the conversion later?

Something like this:

#[derive(Debug, Parser)]
pub struct Config {
    #[clap( ??? )]
    interval: std::time::Duration,
}
like image 812
ddulaney Avatar asked Dec 01 '25 05:12

ddulaney


1 Answers

Clap 3.0:

To do custom parsing, you should use #[clap(parse(try_from_str = ...))] and define a custom function to parsing the argument. Here's an example:

use clap::Parser;

#[derive(Debug, Parser)]
pub struct Config {
    #[clap(parse(try_from_str = parse_duration))]
    interval: std::time::Duration,
}

fn parse_duration(arg: &str) -> Result<std::time::Duration, std::num::ParseIntError> {
    let seconds = arg.parse()?;
    Ok(std::time::Duration::from_secs(seconds))
}

Clap 4.0:

Almost same as above; the helper function can stay the same, but the attribute syntax has changed:

use clap::Parser;

#[derive(Debug, Parser)]
pub struct Config {
    #[arg(value_parser = parse_duration)]
    interval: std::time::Duration,
}

fn parse_duration(arg: &str) -> Result<std::time::Duration, std::num::ParseIntError> {
    let seconds = arg.parse()?;
    Ok(std::time::Duration::from_secs(seconds))
}

Parsing with humantime

This parsing is pretty limited (I don't know what format you'd expect the duration to be in), but it shows how you'd do it.

If you want to be flexible with your duration arguments, consider using a crate like humantime, which lets you provide durations with unit labels like "5s" or "3 hours". You can either use their helper function to parse into a std::time::Duration (using clap 4 syntax):

use clap::Parser;

#[derive(Debug, Parser)]
pub struct Config {
    #[clap(value_parser = humantime::parse_duration, default_value = "500ms")]
    interval: std::time::Duration,
}

Or you can use humantime::Duration without special attributes since it implements FromStr.

use clap::Parser;

#[derive(Debug, Parser)]
pub struct Config {
    #[clap(default_value = "500ms")]
    interval: humantime::Duration,
}
like image 129
kmdreko Avatar answered Dec 04 '25 07:12

kmdreko



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!