You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将Excel日期浮点数转换为Rust的chrono::NaiveDate或年月日组件

在Rust中把Excel浮点数日期转换为chrono::NaiveDate

核心逻辑说明

Excel的日期数值是从1900年1月1日开始计数的天数,但存在1900年闰年bug(Excel错误认为1900是闰年,多算了一天),所以需要先修正这个问题,再转成NaiveDate:

  • 当日期数值≥60时,实际天数需要减1(跳过不存在的1900-02-29)
  • 日期数值<60时直接使用原整数天数
  • 基于修正后的天数,从基准日期1900-01-01累加得到目标日期

补充后的Float分支代码

把你原有代码中的Float分支替换为以下逻辑:

Ok(DataType::Float(dt)) => {
    println!("this is float!!!");
    println!("dt: {}", dt);
    // 提取整数天数部分,Excel日期的小数是时间,这里只取日期部分
    let mut days = dt.floor() as i64;
    // 修正Excel的1900闰年bug
    if days >= 60 {
        days -= 1;
    }
    // Excel基准日期是1900-01-01,对应天数1,所以要减1才能用chrono的add_days
    let base_date = NaiveDate::from_ymd_opt(1900, 1, 1).unwrap();
    // 计算目标日期,用checked_add_days避免溢出
    let val = base_date.checked_add_days(Duration::days(days - 1));
    Ok(val)
}

完整代码示例(整合后)

use chrono::{NaiveDate, Duration};
use calamine::DataType;
// 假设你定义了DATE_FORMAT和Error类型
const DATE_FORMAT: &str = "%d-%m-%Y";
// 替换成你的Error类型定义
type Error = Box<dyn std::error::Error>;

// 你的反序列化逻辑函数
fn deserialize_date<'de, D>(deserializer: D) -> Result<Option<NaiveDate>, Error>
where
    D: serde::Deserializer<'de>,
{
    let data_type = DataType::deserialize(deserializer);
    match data_type {
        Ok(DataType::Error(_)) => Ok(None),
        Ok(DataType::String(date_str)) => {
            let msg = "Failed to convert Date. Wrong format or empty.";
            let val = NaiveDate::parse_from_str(&date_str, DATE_FORMAT)
                .map_err(|_| Error::custom(msg))?;
            Ok(Some(val))
        }
        Ok(DataType::Float(dt)) => {
            println!("this is float!!!");
            println!("dt: {}", dt);
            let mut days = dt.floor() as i64;
            if days >= 60 {
                days -= 1;
            }
            let base_date = NaiveDate::from_ymd_opt(1900, 1, 1).unwrap();
            let val = base_date.checked_add_days(Duration::days(days - 1));
            Ok(val)
        }
        _ => Ok(None),
    }
}

关键细节解释

  1. 取整数天数:用floor()提取浮点数的整数部分,因为Excel的小数部分代表一天中的时间,我们只需要日期部分。
  2. 闰年bug修正:Excel中数值60对应不存在的1900-02-29,所以所有≥60的数值都要减1,才能对应真实的公历日期。
  3. 基准日期计算:Excel的数值1对应1900-01-01,而checked_add_days是从基准日期往后加N天,所以需要用days - 1来匹配。
  4. 安全处理:用checked_add_days替代直接加法,避免因过大的日期数值导致溢出 panic。

内容的提问来源于stack exchange,提问作者DennyHiu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 02:25:16