如何计算不同类型Chrono DateTime对象的Duration差值?
问题描述
我有两个不同类型的DateTime对象,想要对它们执行减法运算,或者通过其他方式获取二者之间的Duration差值。
示例代码如下:
// 第一步:构建不同时区的DateTime对象 // 先创建UTC当前时间对象,再转换为所需时区,例如转换为伦敦时区 let utc_now = Utc::now(); let naive_utc_datetime = utc_now.naive_local(); // 由于该时间是UTC时间,`naive_local`应与`naive_utc`返回相同结果? // 通过chrono_tz时区创建伦敦时间 let london_now = chrono_tz::Europe::London.from_utc_datetime(&naive_utc_datetime); println!("london_now: {}", london_now); // london_now: 2023-08-31 10:07:43.421198168 BST let difference_from_utc = london_now - utc_now; println!("difference_from_utc: {}", difference_from_utc); // 无法编译
编译报错信息:
cannot subtract `DateTime<Utc>` from `DateTime<Tz>` the trait `Sub<DateTime<Utc>>` is not implemented for `DateTime<Tz>` the following other types implement trait `Sub<Rhs>`: <DateTime<Tz> as Sub<Days>> <DateTime<Tz> as Sub<FixedOffset>> <DateTime<Tz> as Sub<Months>> <DateTime<Tz> as Sub<chrono::Duration>> <DateTime<Tz> as Sub>
需求:如何获取伦敦时间与UTC时间之间的Duration差值?当前为英国夏令时,2023-08-31当天的差值应为恰好1小时。
解决方案
要计算不同时区DateTime对象的差值,核心思路是将两个对象转换为同一时区的类型,或直接基于时间戳计算,以下是几种可行方法:
方法1:统一时区后相减
将其中一个DateTime转换为另一个的时区类型,即可直接使用减法运算符得到Duration:
// 将UTC时间转换为伦敦时区的DateTime let utc_in_london = utc_now.with_timezone(&chrono_tz::Europe::London); // 此时两个对象都是DateTime<chrono_tz::Europe::London>类型,可以直接相减 let difference = london_now - utc_in_london; println!("difference_from_utc: {}", difference); // 输出:01:00:00(夏令时期间)
也可以反过来,把伦敦时间转换为UTC时区:
let london_in_utc = london_now.with_timezone(&Utc); let difference = london_in_utc - utc_now; println!("difference_from_utc: {}", difference);
方法2:基于时间戳计算差值
提取两个DateTime的Unix时间戳(精确到秒、毫秒或纳秒),计算差值后转换为Duration:
// 获取纳秒级时间戳 let utc_timestamp = utc_now.timestamp_nanos(); let london_timestamp = london_now.timestamp_nanos(); // 计算差值并转为Duration let difference = chrono::Duration::nanos(london_timestamp - utc_timestamp); println!("difference_from_utc: {}", difference);
这种方法不受时区类型限制,适用于任意DateTime对象的差值计算。
方法3:直接获取时区偏移量(仅适用于同一时刻的不同时区表示)
如果两个DateTime表示的是同一物理时刻(比如示例中伦敦时间由UTC时间转换而来),可以直接获取伦敦时区的偏移量:
// 获取伦敦时间的时区偏移(相对于UTC) let offset = london_now.offset(); // 转换为Duration let difference = chrono::Duration::seconds(offset.local_minus_utc() as i64); println!("difference_from_utc: {}", difference);
这种方法效率最高,但仅适用于两个时间点为同一时刻的场景。
内容的提问来源于stack exchange,提问作者user2138149
相关产品推荐
相关产品推荐

