12个版本
0.3.1 | 2023年7月23日 |
---|---|
0.3.0 | 2022年12月20日 |
0.2.0 | 2022年7月31日 |
0.1.2 | 2022年7月24日 |
0.0.6 | 2022年7月23日 |
#485 in Rust模式
29KB
273 行
custom-format
这个crate通过提供自定义格式化宏,扩展了标准格式化语法,支持自定义格式说明符。
它使用 :
(一个空格和一个冒号)作为格式说明符前的分隔符,这不是当前接受的语法,但它允许在自定义说明符之外还支持标准说明符。它还支持即使在较旧的Rust版本上,也支持格式参数捕获,因为它在缺少时手动添加了命名参数。
这个库有两种风味,对应以下功能
-
编译时
(默认启用)可能的自定义格式说明符集在编译时定义,因此可以在编译时检查无效的说明符。这允许库具有与使用标准库格式化特性相同的性能。
-
运行时
(默认启用)格式化方法在每个调用时动态检查格式说明符。这是一个较慢的版本,但它具有额外的灵活性。
文档
文档托管在docs.rs。
示例
代码
use custom_format as cfmt;
use core::fmt;
pub struct DateTime {
year: i32,
month: u8,
month_day: u8,
hour: u8,
minute: u8,
second: u8,
nanoseconds: u32,
}
macro_rules! impl_custom_format_for_datetime {
(match spec { $($spec:literal => $func:expr $(,)?)* }) => {
use cfmt::compile_time::{spec, CustomFormat};
$(
impl CustomFormat<{ spec($spec) }> for DateTime {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
($func as fn(&Self, &mut fmt::Formatter) -> fmt::Result)(self, f)
}
}
)*
};
}
// Static format specifiers, checked at compile-time
impl_custom_format_for_datetime!(match spec {
// Year with pad for at least 4 digits
"%Y" => |this, f| write!(f, "{:04}", this.year),
// Year % 100 (00..99)
"%y" => |this, f| write!(f, "{:02}", (this.year % 100).abs()),
// Month of the year, zero-padded (01..12)
"%m" => |this, f| write!(f, "{:02}", this.month),
// Day of the month, zero-padded (01..31)
"%d" => |this, f| write!(f, "{:02}", this.month_day),
// Hour of the day, 24-hour clock, zero-padded (00..23)
"%H" => |this, f| write!(f, "{:02}", this.hour),
// Minute of the hour (00..59)
"%M" => |this, f| write!(f, "{:02}", this.minute),
// Second of the minute (00..60)
"%S" => |this, f| write!(f, "{:02}", this.second),
// Date (%m/%d/%y)
"%D" => {
|this, f| {
let month = cfmt::custom_formatter!("%m", this);
let day = cfmt::custom_formatter!("%d", this);
let year = cfmt::custom_formatter!("%y", this);
write!(f, "{}/{}/{}", month, day, year)
}
}
});
// Dynamic format specifiers, checked at runtime
impl cfmt::runtime::CustomFormat for DateTime {
fn fmt(&self, f: &mut fmt::Formatter, spec: &str) -> fmt::Result {
let mut chars = spec.chars();
match (chars.next(), chars.next_back()) {
// Nanoseconds with n digits (%nN)
(Some('%'), Some('N')) => match chars.as_str().parse() {
Ok(n) if n > 0 => {
if n <= 9 {
write!(f, "{:0width$}", self.nanoseconds / 10u32.pow(9 - n as u32), width = n)
} else {
write!(f, "{:09}{:0width$}", self.nanoseconds, 0, width = n - 9)
}
}
_ => Err(fmt::Error),
},
_ => Err(fmt::Error),
}
}
}
let dt = DateTime {
year: 1836,
month: 5,
month_day: 18,
hour: 23,
minute: 45,
second: 54,
nanoseconds: 123456789,
};
// Expands to:
//
// match (&("DateTime"), &dt) {
// (arg0, arg1) => ::std::println!(
// "The {0:?} is: {1}-{2}-{3} {4}:{5}:{6}.{7}",
// arg0,
// ::custom_format::custom_formatter!("%Y", arg1),
// ::custom_format::custom_formatter!("%m", arg1),
// ::custom_format::custom_formatter!("%d", arg1),
// ::custom_format::custom_formatter!("%H", arg1),
// ::custom_format::custom_formatter!("%M", arg1),
// ::custom_format::custom_formatter!("%S", arg1),
// ::custom_format::runtime::CustomFormatter::new("%6N", arg1)
// ),
// }
//
// Output: `The "DateTime" is: 1836-05-18 23:45:54.123456`
//
// The custom format specifier is interpreted as a compile-time specifier by default,
// or as a runtime specifier if it is inside "<>".
cfmt::println!(
"The {ty:?} is: {dt :%Y}-{dt :%m}-{dt :%d} {dt :%H}:{dt :%M}:{dt :%S}.{dt :<%6N>}",
ty = "DateTime",
);
// Compile-time error since "%h" is not a valid format specifier
// cfmt::println!("{0 :%h}", dt);
// Panic at runtime since "%h" is not a valid format specifier
// cfmt::println!("{0 :<%h>}", dt);
编译器支持
需要rustc 1.56+
。
许可证
本项目许可采用Apache License,版本2.0或MIT许可证。
任选其一。
除非你明确声明,否则你故意提交以供包含在本项目中的任何贡献,根据Apache-2.0许可证定义,应如上双重许可,不附加任何额外条款或条件。
依赖项
~195KB