Skip to content
On this page

sheetjs导出表格时间错误问题

最近使用sheetjs,前端web去导出生成excel,xlsx表格。其中遇到一种问题,那就是时间出错了!比如多出8小时43秒少了43秒。看到这种问题的时候,我也一脸懵逼。先上图!

时间错误示例图1

时间错误示例图2

  • 不过在有些人电脑上导出时间确实非常的正确!

时间正确示例图1

错误显示的原因?

我找到了相关的文章描述该问题 GitHub地址

在当地时间 1901-01-01 00:00:00,上海时区由 LMT(Local Mean Time)切换为 CST (China Standard Time),与 GMT 的时差由 + 8:05:43 调整为 + 8:00:00。

所以有些机器上的时区切换导致时差调整不正确,所以前端js导出表格的时候,字符串转换成Date类型出现的时差误差错误,所以在表格生成的时候,日期出现多了多出8小时43秒少了43秒等等现象。

解决办法

直接算出误差的时间秒数,加上去就行了,下面就是js代码。

js
/**
 * 获取当前机器时间时区是否存在时间误差
 * @param {Date} date 比对的误差时间
 * @returns {Number} 误差毫秒
 */
function getTimezoneOffsetMS(date) {
  var time = date.getTime();
  var utcTime = Date.UTC(date.getFullYear(),
    date.getMonth(),
    date.getDate(),
    date.getHours(),
    date.getMinutes(),
    date.getSeconds(),
    date.getMilliseconds());
  return time - utcTime;
}

/**
 * 矫正日期误差
 * @param {Date} date 需要矫正的日期
 * @returns {Date} 返回矫正后的日期
 */
function fixDate(date) {
  const importBugHotfixDiff = (function () {
    const basedate = new Date(1899, 11, 30, 0, 0, 0);
    const dnthreshAsIs = (new Date().getTimezoneOffset() - basedate.getTimezoneOffset()) * 60000;
    const dnthreshToBe = getTimezoneOffsetMS(new Date()) - getTimezoneOffsetMS(basedate);
    return dnthreshAsIs - dnthreshToBe;
  }());
  return (new Date(date.getTime() + importBugHotfixDiff));
}


/**
 * 是否需要矫正日期
 * @param {Date} date 需要判断的日期
 * @returns {Boolean}  是否需要矫正
 */
function isNeedFixDate(date) {
  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();
  return new Date(date.valueOf() - timezoneOffsetFix).getTimezoneOffset() !== baseDate.getTimezoneOffset();
}

// 正常情况 时差没问题的 会显示这样
fixDate(new Date('2023-01-02 00:00:00')) // Mon Jan 02 2023 00:00:00 GMT+0800 (GMT+08:00)

// 下面是时差有问题的 
fixDate(new Date('2023-01-02 00:00:00')) // Sun Jan 01 2023 23:59:17 GMT+0800

按照修改后的时间,再调用sheetjs的方法导出xlsx后,时间就不会出错了。

案例demo地址