chrono::offset::FixedOffset不能由Crate clap使用,因为它没有实现FromStr特性



我正在为Rust中的命令行工具编写代码。我使用Crate clap来获取和解析命令行参数,我需要获得三个参数:--date--time--timezone

对于--date--time,我分别使用了类型chrono::NaiveDate和chrono::NaiveTime,效果很好。

src/main.rs

use clap::Parser;
use chrono::prelude::*;

// CLI struct
#[derive(Parser, Debug)]
#[command(author, version, about, long_about = None)] // Read from `Cargo.toml`
pub struct Cli {
/// Select a date in format YYYY-MM-DD.
#[arg(short, long, value_name = "DATE")]
date: Option<NaiveDate>,
/// Clocking time in format HH:MM:SS
#[arg(short, long, value_name = "TIME")]
time: Option<NaiveTime>,
}
fn main() {
let _cli: Cli = Cli::parse();
println!("{:#?}", _cli);
}

输出

$ cargo run -- --date 2021-05-13 --time 08:34:23
Finished dev [unoptimized + debuginfo] target(s) in 2.28s
Running `target/debug/tool --date 2021-05-13 --time '08:34:23'`
Cli {
date: Some(
2021-05-13,
),
time: Some(
08:34:23,
),
}

但是当我想添加--timezone参数并将其用作类型chrono::FixedOffset时,就像这样:

[...]
pub struct Cli {
/// Select a date in format YYYY-MM-DD.
#[arg(short, long, value_name = "DATE")]
date: Option<NaiveDate>,
/// Clocking time in format HH:MM:SS
#[arg(short, long, value_name = "TIME")]
time: Option<NaiveTime>,
/// Define local TimeZone
#[arg(long, value_name = "TIMEZONE")]
timezone: Option<FixedOffset>,
}
[...]

Rust编译器显示此错误:

$ cargo run -- --date 2021-05-13 --time 08:34:23
Compiling tool v0.1.0 (~/rust/tool)
error[E0599]: the method `value_parser` exists for reference `&&&&&&_AutoValueParser<chrono::FixedOffset>`, but its trait bounds were not satisfied
--> src/main.rs:19:5
|
19   |     /// Define local TimeZone
|     ^^^^^^^^^^^^^^^^^^^^^^^^^ method cannot be called on `&&&&&&_AutoValueParser<chrono::FixedOffset>` due to unsatisfied trait bounds
|
::: ~/.cargo/registry/src/github.com-1ecc6299db9ec823/clap-4.0.18/src/builder/value_parser.rs:2171:1
|
2171 | pub struct _AutoValueParser<T>(std::marker::PhantomData<T>);
| ------------------------------ doesn't satisfy `_: clap::builder::via_prelude::_ValueParserViaParse`
|
::: ~/.cargo/registry/src/github.com-1ecc6299db9ec823/chrono-0.4.22/src/offset/fixed.rs:27:1
|
27   | pub struct FixedOffset {
| ----------------------
| |
| doesn't satisfy `chrono::FixedOffset: From<&'s std::ffi::OsStr>`
| doesn't satisfy `chrono::FixedOffset: From<&'s str>`
| doesn't satisfy `chrono::FixedOffset: From<OsString>`
| doesn't satisfy `chrono::FixedOffset: From<std::string::String>`
| doesn't satisfy `chrono::FixedOffset: FromStr`
| doesn't satisfy `chrono::FixedOffset: ValueEnum`
| doesn't satisfy `chrono::FixedOffset: ValueParserFactory`
|
= note: the following trait bounds were not satisfied:
`chrono::FixedOffset: ValueEnum`
which is required by `&&&&&_AutoValueParser<chrono::FixedOffset>: clap::builder::via_prelude::_ValueParserViaValueEnum`
`chrono::FixedOffset: ValueParserFactory`
which is required by `&&&&&&_AutoValueParser<chrono::FixedOffset>: clap::builder::via_prelude::_ValueParserViaFactory`
`chrono::FixedOffset: From<OsString>`
which is required by `&&&&_AutoValueParser<chrono::FixedOffset>: clap::builder::via_prelude::_ValueParserViaFromOsString`
`chrono::FixedOffset: From<&'s std::ffi::OsStr>`
which is required by `&&&_AutoValueParser<chrono::FixedOffset>: clap::builder::via_prelude::_ValueParserViaFromOsStr`
`chrono::FixedOffset: From<std::string::String>`
which is required by `&&_AutoValueParser<chrono::FixedOffset>: clap::builder::via_prelude::_ValueParserViaFromString`
`chrono::FixedOffset: From<&'s str>`
which is required by `&_AutoValueParser<chrono::FixedOffset>: clap::builder::via_prelude::_ValueParserViaFromStr`
`chrono::FixedOffset: FromStr`
which is required by `_AutoValueParser<chrono::FixedOffset>: clap::builder::via_prelude::_ValueParserViaParse`
= note: this error originates in the macro `clap::value_parser` (in Nightly builds, run with -Z macro-backtrace for more info)
For more information about this error, try `rustc --explain E0599`.
error: could not compile `tool` due to 2 previous errors

我应该为timezone变量使用另一种类型吗
是否应该将FromStr特征实现为FixedOffset结构?

我可以使用timezone变量作为Type String,它是有效的,但我想使用TimeZone或Offset的特定类型,例如,来保存+01:00值。我将不得不孤立地管理此参数。

我不想使用chrono::DateTime结构,因为我会为这些参数使用默认值,通常,用户只会定义--time参数,我不会强迫他编写所有DateTime。

谢谢

您无法为FixedOffset实现FromStr,因为您既没有编写FromStr特征,也没有编写FixedOffset结构,而且还存在孤立规则。然而,您确实需要编写一个函数,将字符串转换为FixedOffset,并使用value_parser属性将其传递给clap:

use clap::Parser;
use chrono::prelude::*;

// CLI struct
#[derive(Parser, Debug)]
#[command(author, version, about, long_about = None)] // Read from `Cargo.toml`
pub struct Cli {
/// Select a date in format YYYY-MM-DD.
#[arg(short, long, value_name = "DATE")]
date: Option<NaiveDate>,
/// Clocking time in format HH:MM:SS
#[arg(short, long, value_name = "TIME")]
time: Option<NaiveTime>,
/// Define local TimeZone
#[arg(long, value_name = "TIMEZONE", value_parser = parse_timezone)]
timezone: Option<FixedOffset>,
}
fn parse_timezone (tz: &str) -> Result<FixedOffset, &'static str> {
/// TODO: Parse the string timezone into a `FixedOffset`
Err ("Not implemented")
}
fn main() {
let _cli: Cli = Cli::parse();
println!("{:#?}", _cli);
}

游乐场

相关内容

最新更新