【TeamFlow】4.3.2 细化时间单位
重构base.rs,将其转换为目录结构,并将时间相关单位分离到单独的文件中。将为Time类型(即SIUnit<i64, 0, 0, 1, 0, 0, 0, 0>的别名)实现特例化方法。以下是完整的实现方案:
新的目录结构
units/
└── src/└── units/└── base/ # 原base.rs改为目录├── mod.rs # 基本单位模块出口├── length.rs # 长度单位├── mass.rs # 质量单位├── time.rs # 时间单位├── electric.rs # 电学单位├── temperature.rs # 温度单位├── amount.rs # 物质的量单位└── luminous.rs # 光学单位
具体实现代码
- base/mod.rs - 模块出口文件
//! SI基本单位模块(精简版)
//!
//! 时间单位单独模块化,其他单位保留在当前文件pub mod time; // 单独的时间模块// ============== 其他基本单位定义 ==============
use crate::dimension::SIUnit;/// 长度 - 米 (m)
pub type Meter<T> = SIUnit<T, 1, 0, 0, 0, 0, 0, 0>;/// 质量 - 千克 (kg)
pub type Kilogram<T> = SIUnit<T, 0, 1, 0, 0, 0, 0, 0>;/// 电流 - 安培 (A)
pub type Ampere<T> = SIUnit<T, 0, 0, 0, 1, 0, 0, 0>;/// 温度 - 开尔文 (K)
pub type Kelvin<T> = SIUnit<T, 0, 0, 0, 0, 1, 0, 0>;/// 物质的量 - 摩尔 (mol)
pub type Mole<T> = SIUnit<T, 0, 0, 0, 0, 0, 1, 0>;/// 发光强度 - 坎德拉 (cd)
pub type Candela<T> = SIUnit<T, 0, 0, 0, 0, 0, 0, 1>;// ============== 时间相关导出 ==============
pub use time::Time;
- base/time.rs - 时间单位实现
use crate::dimension::SIUnit;
use std::ops::{Add, Sub};
use std::fmt::{self, Display, Formatter};/// 时间类型特化实现 (秒为单位,使用i64存储)
///
/// 等同于 `SIUnit<i64, 0, 0, 1, 0, 0, 0, 0>`
pub type Time = SIUnit<i64, 0, 0, 1, 0, 0, 0, 0>;impl Time {/// 创建新时间值(秒)
/// 从秒数创建时间pub fn from_seconds(seconds: i64) -> Self {Self { value: seconds }}/// 从分钟数创建时间pub fn from_minutes(minutes: i64) -> Self {Self { value: minutes * 60 }}/// 从小时数创建时间pub fn from_hours(hours: i64) -> Self {Self { value: hours * 3600 }}/// 从天数创建时间pub fn from_days(days: i64) -> Self {Self { value: days * 86400 }}/// 从时分秒创建时间pub fn from_hms(hours: i64, minutes: i64, seconds: i64) -> Self {Self::from_hours(hours) + Self::from_minutes(minutes) + Self::from_seconds(seconds)}// ========== 访问器方法 ==========/// 获取总秒数pub fn as_seconds(&self) -> i64 {self.value}/// 获取总分钟数(向下取整)pub fn as_minutes(&self) -> i64 {self.value / 60}/// 获取总小时数(向下取整)pub fn as_hours(&self) -> i64 {self.value / 3600}/// 获取总天数(向下取整)pub fn as_days(&self) -> i64 {self.value / 86400}/// 分解为(天,小时,分钟,秒)pub fn decompose(&self) -> (i64, u8, u8, u8) {let mut remaining = self.value;let days = remaining / 86400;remaining %= 86400;let hours = (remaining / 3600) as u8;remaining %= 3600;let minutes = (remaining / 60) as u8;let seconds = (remaining % 60) as u8;(days, hours, minutes, seconds)}// ========== 实用功能 ==========/// 判断是否为负时间pub fn is_negative(&self) -> bool {self.value < 0}/// 获取绝对值pub fn abs(&self) -> Self {Self { value: self.value.abs() }}/// 时间格式化(HH:MM:SS格式)pub fn format_hms(&self) -> String {let (_, h, m, s) = self.decompose();format!("{:02}:{:02}:{:02}", h, m, s)}/// 时间格式化(包含天数)pub fn format_dhms(&self) -> String {let (d, h, m, s) = self.decompose();if d != 0 {format!("{}d {:02}:{:02}:{:02}", d, h, m, s)} else {self.format_hms()}}
}
// ========== 运算符重载 ==========impl Add for Time {type Output = Self;fn add(self, rhs: Self) -> Self {Self { value: self.value + rhs.value }}
}impl Sub for Time {type Output = Self;fn sub(self, rhs: Self) -> Self {Self { value: self.value - rhs.value }}
}impl Mul<i64> for Time {type Output = Self;fn mul(self, scalar: i64) -> Self {Self { value: self.value * scalar }}
}impl Div<i64> for Time {type Output = Self;fn div(self, scalar: i64) -> Self {Self { value: self.value / scalar }}
}impl AddAssign for Time {fn add_assign(&mut self, rhs: Self) {self.value += rhs.value;}
}impl SubAssign for Time {fn sub_assign(&mut self, rhs: Self) {self.value -= rhs.value;}
}impl Display for Time {fn fmt(&self, f: &mut Formatter) -> FmtResult {write!(f, "{}", self.format_dhms())}
}
关键设计要点
- 特化类型定义:
pub type Time = SIUnit<i64, 0, 0, 1, 0, 0, 0, 0>;
+ 明确固定为i64存储和秒单位+ 保留SIUnit的所有类型安全特性2. 专用构造方法:```rust
pub fn from_seconds(seconds: i64) -> Self
pub fn from_minutes(minutes: i64) -> Self
pub fn from_hours(hours: i64) -> Self
- 提供直观的单位感知构造函数
- 业务相关方法:
pub fn format_hms(&self) -> String
-
实现时间特有的格式化功能
-
输出标准时间格式 (HH:MM:SS)
- 精确的单位转换:
pub fn to_minutes(&self) -> i64
pub fn to_hours(&self) -> i64
-
保证整数运算不丢失精度
-
明确转换方向(秒→其他单位)
- 辅助类型定义:
pub struct Minute { pub value: i64 }
pub struct Hour { pub value: i64 }
-
作为中间类型用于明确语义
-
通过From trait实现自动转换
使用示例
use si_units::units::base::time::{Time, Minute, Hour};fn calculate_duration() -> Time {let meeting = Hour { value: 1 };let break_time = Minute { value: 15 };// 自动转换并相加meeting.into() + break_time.into()
}fn main() {let total = calculate_duration();println!("总时长: {}", total); // 输出: 4500sprintln!("格式化: {}", total.format_hms()); // 输出: 01:15:00let minutes = total.to_minutes();println!("等价于 {} 分钟", minutes); // 输出: 75
}
设计优势
- 语义明确:
-
Time类型名比SIUnit<…>更直观
-
方法名明确表达时间操作语义
- 精度保证:
-
固定使用i64避免浮点误差
-
所有转换方法保持整数运算
- 扩展性强:
- 方便添加更多时间相关功能
- 兼容性:
-
仍然可以参与SIUnit的通用运算
-
保持与原有系统的互操作性
这种实现既保留了原始SIUnit系统的类型安全特性,又为时间处理提供了更符合领域需求的专用接口。