使用 clap 的#[derive(Parser)],我如何接受 std::time::Duration?

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

我想在命令行上接受 std::time::Duration。我使用 clap#[derive(Parser)] 来生成参数解析器。有什么方法可以直接接受输入,而不是接受一个数字然后再进行转换?

像这样:

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

我认为没有办法在命令行 本身 上将 u8 或其他任何东西与 std::time::Duration 区分开来。也就是说,如果你为 Duration:

实现 FromStr,你应该能够做这样的事情
struct Config {
    #[structopt(short = "i", long = "interval")]
    interval: std::time::Duration,
}

但是使用 u8 之类的东西并在 main() 或类似的格式中进行转换似乎更容易。

要进行自定义解析,您应该使用 #[clap(parse(try_from_str = ...))] 并定义一个自定义函数来解析参数。这是一个例子:

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))
}

此解析非常有限(我不知道您希望持续时间采用哪种格式),但它显示了您将如何进行解析。

如果你想灵活地处理你的持续时间参数,考虑使用像 humantime; their Duration 这样的板条箱可以与没有特殊属性的拍手一起使用,因为它实现了 FromStr.