【Chrono库】Chrono Traits 模块解析(traits.rs)

这是 Chrono 时间库中的 traits 模块,定义了日期和时间组件的基本操作接口。

模块概述

该模块包含两个核心 trait:

  1. Datelike - 日期组件的通用方法集合
  2. Timelike - 时间组件的通用方法集合

Datelike Trait 解析

基本信息获取方法

rust 复制代码
pub trait Datelike: Sized {
    fn year(&self) -> i32;                    // 年份 (包含公元前)
    fn month(&self) -> u32;                   // 月份 (1-12)
    fn month0(&self) -> u32;                  // 月份 (0-11)
    fn day(&self) -> u32;                     // 日 (1-31)
    fn day0(&self) -> u32;                    // 日 (0-30)
    fn ordinal(&self) -> u32;                 // 年中日 (1-366)
    fn ordinal0(&self) -> u32;                // 年中日 (0-365)
    fn weekday(&self) -> Weekday;             // 星期几
    fn iso_week(&self) -> IsoWeek;            // ISO 周
}

便捷计算方法

年份处理

rust 复制代码
fn year_ce(&self) -> (bool, u32) {
    let year = self.year();
    if year < 1 { (false, (1 - year) as u32) } else { (true, year as u32) }
}
  • 返回 (is_ce, year_number) 元组
  • is_ce: true 表示公元后(CE/AD),false 表示公元前(BCE/BC)

季度计算

rust 复制代码
fn quarter(&self) -> u32 {
    (self.month() - 1).div_euclid(3) + 1
}
  • 返回 1-4 的季度数

日期修改方法

警告:这些方法需要谨慎使用,因为:

  • 中间值可能不存在(如 2月29日改为非闰年)
  • 不应连续使用多个 with_* 方法
rust 复制代码
fn with_year(&self, year: i32) -> Option<Self>;     // 修改年份
fn with_month(&self, month: u32) -> Option<Self>;   // 修改月份
fn with_month0(&self, month0: u32) -> Option<Self>; // 修改月份(0-based)
fn with_day(&self, day: u32) -> Option<Self>;       // 修改日
fn with_day0(&self, day0: u32) -> Option<Self>;     // 修改日(0-based)
fn with_ordinal(&self, ordinal: u32) -> Option<Self>;   // 修改年中日
fn with_ordinal0(&self, ordinal0: u32) -> Option<Self>; // 修改年中日(0-based)

错误情况

  • 结果日期不存在(如 2月29日改为非闰年)
  • 时区转换问题(对于 DateTime<Tz>
  • 数值超出范围

高级日期计算

儒略日计算

rust 复制代码
fn num_days_from_ce(&self) -> i32 {
    // 计算从公元1年1月1日开始的日数
    let mut year = self.year() - 1;
    let mut ndays = 0;
    // 处理公元前年份
    if year < 0 {
        let excess = 1 + (-year) / 400;
        year += excess * 400;
        ndays -= excess * 146_097;  // 400年的天数
    }
    let div_100 = year / 100;
    ndays += ((year * 1461) >> 2) - div_100 + (div_100 >> 2);
    ndays + self.ordinal() as i32
}

月份天数

rust 复制代码
fn num_days_in_month(&self) -> u8 {
    use num_traits::FromPrimitive;
    let month = Month::from_u32(self.month()).unwrap();
    month.num_days(self.year()).unwrap()
}

Timelike Trait 解析

基本信息获取

rust 复制代码
pub trait Timelike: Sized {
    fn hour(&self) -> u32;        // 小时 (0-23)
    fn minute(&self) -> u32;      // 分钟 (0-59)
    fn second(&self) -> u32;      // 秒 (0-59)
    fn nanosecond(&self) -> u32;  // 纳秒 (0-1,999,999,999)
}

时间格式转换

12小时制

rust 复制代码
fn hour12(&self) -> (bool, u32) {
    let hour = self.hour();
    let mut hour12 = hour % 12;
    if hour12 == 0 { hour12 = 12; }  // 0点转为12点
    (hour >= 12, hour12)  // (is_pm, hour_12)
}

时间修改方法

rust 复制代码
fn with_hour(&self, hour: u32) -> Option<Self>;      // 修改小时
fn with_minute(&self, min: u32) -> Option<Self>;     // 修改分钟
fn with_second(&self, sec: u32) -> Option<Self>;     // 修改秒
fn with_nanosecond(&self, nano: u32) -> Option<Self>; // 修改纳秒

时间计算

午夜后秒数

rust 复制代码
fn num_seconds_from_midnight(&self) -> u32 {
    self.hour() * 3600 + self.minute() * 60 + self.second()
}

测试模块

儒略日计算验证

测试中提供了一个替代实现来验证 num_days_from_ce 的正确性:

rust 复制代码
fn num_days_from_ce<Date: Datelike>(date: &Date) -> i32 {
    let year = date.year();
    let diff = move |div| in_between(1, year, div);
    date.ordinal() as i32 + 365 * diff(1) + diff(4) - diff(100) + diff(400)
}

这个实现更直观地展示了闰年规则:

  • 每年365天
  • 每4年加1天(闰年)
  • 每100年减1天(例外)
  • 每400年加1天(例外中的例外)

月份天数测试

验证不同情况下月份天数的正确性:

  • 闰年2月:29天
  • 平年2月:28天
  • 大月:31天

设计特点

  1. 零基和壹基并存 :提供 month()/month0() 等对应方法
  2. 错误安全 :修改方法返回 Option<Self>
  3. 性能优化:使用位运算和数学优化
  4. 完整性:支持公元前日期和闰秒
  5. 实用性:提供常用计算如季度、12小时制等

使用注意事项

  1. 避免链式修改 :不要连续调用多个 with_* 方法
  2. 理解语义with_year 保持月日不变,可能改变序数日
  3. 时区考虑:对于有时区的日期时间,修改可能涉及时区转换问题

这些 trait 为 Chrono 库提供了统一的日期时间操作接口,确保了类型安全和操作的一致性。

相关推荐
穆雄雄11 小时前
Rust 程序适配 OpenHarmony 实践:以 sd 工具为例
开发语言·rust·harmonyos
Easonmax1 天前
用 Rust 打造可复现的 ASCII 艺术渲染器:从像素到字符的完整工程实践
开发语言·后端·rust
百锦再1 天前
选择Rust的理由:从内存管理到抛弃抽象
android·java·开发语言·后端·python·rust·go
小羊失眠啦.1 天前
深入解析Rust的所有权系统:告别空指针和数据竞争
开发语言·后端·rust
受之以蒙1 天前
Rust ndarray 高性能计算:从元素操作到矩阵运算的优化实践
人工智能·笔记·rust
非专业程序员1 天前
Rust RefCell 多线程读为什么也panic了?
rust·swift
小羊失眠啦.1 天前
用 Rust 实现高性能并发下载器:从原理到实战
开发语言·后端·rust
凯子坚持 c1 天前
从 API 到应用:用 Rust 和 SQLx 为 Axum 服务添加持久化数据库
数据库·oracle·rust
LXA08091 天前
在Vue 3项目中配置和使用SCSS
vue.js·rust·scss