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

关于Excel序列号转日期JavaScript代码的两处技术疑问

Excel序列号转日期JavaScript代码疑问解答
async function getNewDate(xlSerial) {
    // milliseconds since 1899-31-12T00:00:00Z, corresponds to xl serial 0.
    let xlSerialOffset = -2209075200000; 
    let elapsedDays;
    // each serial up to 60 corresponds to a valid calendar date.
    // serial 60 is 1900-02-29. This date does not exist on the calendar.
    // we choose to interpret serial 60 (as well as 61) both as 1900-03-01
    // so, if the serial is 61 or over, we have to subtract 1.
    if (xlSerial < 61) {
        elapsedDays = xlSerial;
    }
    else {
        elapsedDays = xlSerial - 1;
    }
    // javascript dates ignore leap seconds
    // each day corresponds to a fixed number of milliseconds:
    // 24 hrs * 60 mins * 60 s * 1000 ms
    let millisPerDay = 86400000;

    let jsTimestamp = xlSerialOffset + elapsedDays * millisPerDay;
    return new Date(jsTimestamp);
}

疑问解答

1. 代码中的let xlSerialOffset = -2209075200000;代表什么含义?

这个数值是JavaScript时间戳与Excel序列号起始点的毫秒偏移量:

  • Excel的序列号0对应日期1899-12-31(代码注释里的1899-31-12是笔误,应为12月31日);
  • JavaScript的时间戳以1970-01-01T00:00:00Z为零点,计算从该零点到1899-12-31T00:00:00Z的毫秒数,结果就是负数的-2209075200000。用这个偏移量加上Excel序列号对应的毫秒数,就能把Excel的日期基准转换为JavaScript的时间戳基准。

2. 当xlSerial≥61时,为什么要执行elapsedDays = xlSerial - 1的操作?

这是为了修正Excel的历史遗留bug:

  • 早期Excel模仿Lotus 1-2-3的日期系统,错误地将1900年判定为闰年,给不存在的1900-02-29分配了序列号60;
  • 但实际1900年不是闰年,没有2月29日。代码里将序列号60和61都映射为真实存在的1900-03-01;
  • 对于序列号≥61的日期,因为Excel多算了那一天(不存在的1900年2月29日),所以必须减1来对齐真实日历,避免后续所有日期都偏差一天。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 20:36:38