如何在Rust中实现带chrono时区的泛型Clock时钟接口?
问题核心原因
你混淆了 chrono 中的时区类型和时区实例的对应关系:TimeZone 是 trait,所有实现该 trait 的类型(比如Utc、Local、chrono_tz中预定义的各国时区)都有对应的零大小单例实例,可以直接获取使用,不需要手动构造。
另外你当前的 Clock trait 设计不符合 trait 对象安全要求:没有&self接收者的关联函数无法通过dyn Clock调用,需要先调整。
调整后的完整实现
1. 修正Clock trait
use chrono::{DateTime, TimeZone, Utc}; /// 满足计时需求的内部时钟trait /// 部分测试环境中可以使用存根时钟实现 pub trait Clock<Tz: TimeZone> { fn now(&self) -> DateTime<Tz>; }
新增&self参数,保证可以构造dyn Clock<Tz> trait 对象用于其他结构体持有。
2. 实现系统时钟
chrono 所有预定义时区类型都实现了Default trait,直接通过默认构造就能拿到对应时区的单例实例,零运行时开销:
/// 可稳定返回指定时区系统时间的时钟实现 #[derive(Debug, Default, Clone, Copy)] struct SystemClock<Tz: TimeZone + Default> { tz: Tz, } impl<Tz: TimeZone + Default> Clock<Tz> for SystemClock<Tz> { /// 返回当前时间 fn now(&self) -> DateTime<Tz> { Utc::now().with_timezone(&self.tz) } }
3. 存根时钟实现示例(用于历史数据重放)
/// 存根时钟,固定返回预设的历史时间 struct StubClock<Tz: TimeZone> { fixed_time: DateTime<Tz>, } impl<Tz: TimeZone> Clock<Tz> for StubClock<Tz> { fn now(&self) -> DateTime<Tz> { self.fixed_time.clone() } }
使用示例
使用UTC时区的系统时钟
let utc_clock = SystemClock::<Utc>::default(); let current_utc_time = utc_clock.now();
使用指定时区的系统时钟(需要引入chrono_tz库)
use chrono_tz::Asia::Shanghai; let shanghai_clock = SystemClock::<Shanghai>::default(); let current_shanghai_time = shanghai_clock.now();
使用存根时钟重放历史时间
let test_time = Utc.with_ymd_and_hms(2024, 5, 1, 12, 0, 0).unwrap(); let stub_clock = StubClock { fixed_time: test_time }; // 无论什么时候调用都返回2024-05-01T12:00:00Z let replay_time = stub_clock.now();
内容的提问来源于stack exchange,提问作者Luke Sneeringer
相关产品推荐
相关产品推荐

