diff --git a/server-rs/crates/module-runtime/src/membership/cycle.rs b/server-rs/crates/module-runtime/src/membership/cycle.rs index 306f8afab..2b29f37e6 100644 --- a/server-rs/crates/module-runtime/src/membership/cycle.rs +++ b/server-rs/crates/module-runtime/src/membership/cycle.rs @@ -34,9 +34,9 @@ pub fn beijing_local_micros(year: i32, month: u8, day: u8, time_of_day_micros: i } Some( days_from_civil(year, month, day) - .saturating_mul(PROFILE_RUNTIME_DAY_MICROS) - .saturating_add(time_of_day_micros) - .saturating_sub(PROFILE_TASK_BEIJING_OFFSET_MICROS), + .checked_mul(PROFILE_RUNTIME_DAY_MICROS)? + .checked_add(time_of_day_micros)? + .checked_sub(PROFILE_TASK_BEIJING_OFFSET_MICROS)?, ) } @@ -119,6 +119,13 @@ mod tests { ); } + #[test] + fn beijing_local_micros_rejects_overflowing_year() { + // 中文注释:超出 i64 微秒范围的年份必须返回 None,而不是饱和成看似合法的值。 + assert_eq!(beijing_local_micros(1_000_000, 1, 1, 0), None); + assert_eq!(beijing_local_micros(-1_000_000, 1, 1, 0), None); + } + #[test] fn advance_months_clamps_to_month_end() { // 中文注释:1/31 开通 → 2/28(2026 非闰年)→ 3/31,每期都从原始锚点重算。