1 format 对时间库的支持
1.1 格式说明
说到 format 对时间库的支持,其实应该反过来说才对,是时间库通过提供针对相关类型的 std::formatter<> 特化版本的方式,使得 format 库也能支持这些类型的格式化输出(侧面也赞美了 format 库的可扩展性设计)。通过这些特化版本,时间库在不引起与其他类型的格式冲突的情况下,给 format() 函数以及 print() 函数(C++ 23)的格式化说明部补充了一些特殊格式说明符。
先会议一下《C++ 的 format 和 vformat 函数》一篇中对格式说明(format-spec)语法形式上的描述:
fill-and-align(optional) sign(optional) #(optional) 0(optional) width(optional) precision(optional) L(optional) type(optional)
这里面的 type(optional) 就是自定义类型向 format 库增加的格式说明,前提是不能与标准的填充与对齐标记符、sign、#、0、width、precision 和 L 冲突。时间库相关类型的格式化不使用 sign、#、0,形式上是这样的:
fill-and-align(optional) width(optional) precision(optional) L(optional) chrono-spec(optional)
其中 fill-and-align、width 和 precision 斗与 format 的标准格式说明一致,实际上,也只有时间间隔类型(std::chrono::duration)才会用到 precision,因为时间间隔的计数值可能是浮点数。
为了不与标准的说明符或其他数据类型的说明符发生冲突,时间库的格式说明符都是以 % 作为说明标记开始,比如用 %H 表示将时间类型中的小时格式化成一个十进制数字字符串,用 %Y 表示将时间类型中的年份格式化成十进制数字字符串。如果要输出 %,就用两个 %% 形式表示。
时间库的格式说明也支持换行和 tab 制表符,但是不用 \n 和 \t,而是用 %n 和 %t ,下面的代码例子中会用到它们。
1.2 默认格式
不使用具体格式说明符,一个空的 {} 占位符也是支持的,不过输出的内容是有类型决定的默认格式,比如时间点,一般是包含年月日和当天的时间,具体到秒:
auto today = current_zone()->to_local(system_clock::now());
auto s = std::format("Now: {}", today);
//Now: 2024-12-01 15:29:06.752022678
对于时间间隔,则是以计数器+时间单位的方式输出,对于时间库预定义的时间单位,则直接输出 d、h、m 等时间单位,比如:
std::chrono::seconds total = 1h + 23min + 40s;
//Time Elapse: 5020s
std::cout << std::format("Time Elapse: {}", total) << std::endl;
auto hour = std::chrono::floor<std::chrono::hours>(total)