admin 管理员组

文章数量: 1184232

文件概述

这个 display.rs 文件为 ISO 8601 库中的核心类型实现了 Display trait,提供了符合标准的人类可读格式输出功能。

核心格式化实现

1. Date 类型的显示格式化

implDisplayforDate{fnfmt(&self, f:&mutfmt::Formatter)->fmt::Result{match*self{// 格式:`2015-11-02` (年月日)Date::YMD{ year, month, day }=>write!(f,"{:04}-{:02}-{:02}", year, month, day),// 格式:`2015-W45-01` (年-周数-星期几)Date::Week{ year, ww, d }=>write!(f,"{:04}-W{:02}-{:02}", year, ww, d),// 格式:`2015-306` (年-年内第几天)Date::Ordinal{ year, ddd }=>write!(f,"{:04}-{:03}", year, ddd),}}}

三种日期格式说明

  • YMD (年月日): 2024-01-15

    • 最常用的日历日期格式
    • 4位年-2位月-2位日
  • Week (周日期): 2024-W03-1

    • 基于周数的日期表示
    • 4位年-W2位周数-1位星期几(1=周一, 7=周日)
  • Ordinal (序数日期): 2024-015

    • 一年中的第几天
    • 4位年-3位年内日数

2. Time 类型的显示格式化

implDisplayforTime{fnfmt(&self, f:&mutfmt::Formatter)->fmt::Result{// 格式:`16:43:16.123+00:00`write!(
            f,"{:02}:{:02}:{:02}.{}+{:02}:{:02}",self.hour,self.minute,self.second,self.millisecond,self.tz_offset_hours,self.tz_offset_minutes
        )}}

时间格式特点

  • 基本格式 HH:MM:SS.mmm
  • 时区信息 +HH:MM -HH:MM
  • 完整示例 16:43:16.123+08:00 (北京时间下午4点43分)
  • 固定显示毫秒 :即使毫秒为0也会显示 .000

3. DateTime 类型的显示格式化

implDisplayforDateTime{fnfmt(&self, f:&mutfmt::Formatter)->fmt::Result{// 格式:`2015-11-02T16:43:16.123+00:00`write!(f,"{}T{}",self.date,self.time)}}

日期时间格式

  • ISO 8601 标准格式 :日期和时间用 T 分隔
  • 组合格式 <Date>T<Time>
  • 示例 2015-11-02T16:43:16.123+08:00

4. Duration 类型的显示格式化

implDisplayforDuration{fnfmt(&self, f:&mutfmt::Formatter)->fmt::Result{matchself{Duration::YMDHMS{
                year, month, day,
                hour, minute, second, millisecond,}=>{// 处理零持续时间特殊情况ifself.is_zero(){write!(f,"P0D")?;returnOk(());}write!(f,"P")?;// 持续时间必须以 P 开头// 日期部分(年月日)if*year >0{write!(f,"{}Y", year)?}if*month >0{write!(f,"{}M", month)?}if*day >0{write!(f,"{}D", day)?}// 时间部分(时分秒)以 T 开头if*hour >0||*minute >0||*second >0||*millisecond >0{write!(f,"T")?}if*hour >0{write!(f,"{}H", hour)?}if*minute >0{write!(f,"{}M", minute)?}// 秒和毫秒处理if*millisecond >0{write!(f,"{}.{}S", second, millisecond)?}elseif*second >0{write!(f,"{}S", second)?}Ok(())}Duration::Weeks(w)=>write!(f,"P{}W", w),}}}

持续时间格式化规则

格式语法

P[nY][nM][nD][T[nH][nM][nS]]

具体格式化策略

  1. 零值特殊处理

    • 所有单位都为0时输出 P0D
    • 避免空的持续时间字符串
  2. 智能省略

    • 只显示非零的时间单位
    • 如果时间部分全部为零,则省略 T 部分
  3. 时间部分分隔

    • 日期和时间部分用 T 明确分隔
    • 即使日期部分为空,时间部分仍需要 T

格式化示例

持续时间值 格式化输出
全零值 P0D
1年2个月 P1Y2M
3天4小时 P3DT4H
5分钟6秒 PT5M6S
7秒123毫秒 PT7.123S
复杂示例 P1Y2M3DT4H5M6.789S
8周 P8W

测试模块

回环测试设计

fntest_duration_reparse(duration:Duration){let serialized =format!("{}", duration);// 序列化为字符串let reparsed =parse_duration(serialized.as_bytes()).unwrap().1;// 重新解析assert_eq!(duration, reparsed);// 验证相等性}

测试策略 :确保格式化输出的字符串能够被正确解析回原始值,验证双向转换的正确性。

具体测试用例

#[test]fndisplay_duration_0(){let duration =Duration::YMDHMS{
        year:2021, month:11, day:16,
        hour:23, minute:26, second:59, millisecond:0,};test_duration_reparse(duration);}#[test]fndisplay_duration_1(){let duration =Duration::YMDHMS{
        year:2021, month:11, day:16,
        hour:23, minute:26, second:59, millisecond:123,};test_duration_reparse(duration);}#[test]fndisplay_duration_2(){let duration =Duration::Weeks(50);test_duration_reparse(duration);}

测试覆盖

  1. 整秒持续时间 :验证不含毫秒的格式化
  2. 含毫秒持续时间 :验证小数秒的格式化
  3. 周持续时间 :验证周格式的特殊处理

设计特点分析

符合标准性

  • 严格遵循 ISO 8601 :所有输出格式都符合标准规范
  • 正确的语法结构 :持续时间以 P 开头,时间部分以 T 分隔

用户体验优化

  • 简洁输出 :省略零值单位,避免冗长表示
  • 特殊情形处理 :为零持续时间提供明确的 P0D 表示
  • 可读性 :格式清晰,易于人类阅读和理解

技术实现质量

  • 模式匹配 :使用 match 语句清晰处理不同变体
  • 错误处理 :正确的 fmt::Result 返回类型
  • 格式化控制 :使用 {:04} 等格式化指定符确保位数正确

可靠性保障

  • 完整测试 :通过回环测试验证格式化的正确性
  • 边界情况 :测试了零值、含毫秒、周数等边界情况
  • 双向一致性 :确保序列化-反序列化的双向一致性

这个显示格式化模块为 ISO 8601 库提供了完整、标准兼容的输出功能,使得时间相关的数据类型可以方便地转换为人类可读的字符串表示,同时保证了与解析功能的双向一致性。

本文标签: 持续时间 类型的显 格式