前景提要

一个时区与零时区的时差在各个历史时期是不同的。 知乎

为了解决这个问题 sheetjs 使用了偏差值。

如果不是对解析的时间对象操作(例:操作 new Date())会导致有偏差值。

举个栗子

excel 中 时间字段值为 2022/04/22 22:00:02 ,通过解析后获取到的时间是 2022/04/22 21:59:19,此时就出现了偏差 43s

分为两种现象

  • 时间类型的字段,读取和导出没有进行任何操作.本情况没有 bug.

    1
    这种情况是因为sheetjs,对解析的时间先减少偏差值,导出时又加偏差值所以没有问题。
  • 时间类型的字段进行操作或者是通过别的方式赋值.本情况有 bug.会出现偏差值

    1
    2
    3
    这种情况是我们直接赋值,所以并没有sheetjs先进行减少偏差值的操作,导出时加了偏差值所以导致时间不一致。

    例子: new Date() 导出 会比当期时间多43s

解决方案

先计算时区偏差值,再判断是否需要使用偏差值

1
2
3
4
5
6
7
8
9
10
11
const baseDate = new Date(1899, 11, 30, 0, 0, 0);
const baseDateUtc = new Date(Date.UTC(1899, 11, 30, 0, 0, 0));
const timezoneOffsetFix =
baseDateUtc.valueOf() +
baseDate.getTimezoneOffset() * 60000 -
baseDate.valueOf();

const date = moment('2022-04-22 22:00:02').toDate();
const needFix = new Date(date.valueOf() - timezoneOffsetFix).getTimezoneOffset() !== baseDate.getTimezoneOffset();
const fixedDate = needFix ? new Date(date.valueOf() - timezoneOffsetFix) : date;
console.log(moment(fixedDate).format('YYYY-MM-DD HH:mm:ss')); // 2022/04/22 21:59:19

本解决方案来自Github