最近在做 Excel 的导入导出,上传时候遇到时间的问题,这里做简单的记录。
UNIX 时间:
我们知道,在数据库中,时间的存储是以 UTC 时间,1970-01-01 的午夜作为 0,其他所有时间存储的是以这个时间为基础的数字。这是前话,暂且不提。
Excel 中的时间:
当我们要上传一个 Excel 的时候,需要对 Excel 中的内容进行解析。用一些库很容易就能实现,比如前端我们会使用 sheet.js 来实现。
时间有两种形式,string 格式 或者 date 格式。
- string 当然没有问题。
- date 格式很容易想到,它存储的应该是 UNIX 时间,但是实验后发现不是,发现它是一个五位的数字。很明显小于 UNIX 时间的数字。
- 查阅资料后发现,它存储的是所谓的 1904 或者 1900 Date Systems。即:1900 年或者 1904 以后,每增加一天,数字加一,时分秒用小数表示。
Sheet.js 中的处理:
Sheet.js 中也提供了相应的文档: Dates and Times | SheetJS Community Edition。
- 在解析 Excel 的时候,提供了一个参数将 date 格式的数字转换成 date string。 只需要设置
{ cell*Date*s: true }。看起来所有的问题就解决了。 - 实际上,依然存在问题:比如文档中包含时间
2048-10-06 15:00:00解析出来的时间是:2048-10-06T06:59:17.000Z少了43s。这应该是 sheet.js 中的一个 bug。
中国时间的时区转换:
因为 1900 日期系统中是以 1900 年为基准的,我们尝试将 1900-01-01 转换为中国时间,就会发现问题:
- UTC 到 中国时间应该是 8 小时,而不应该有分秒的差别。
- 这里的中国时区不是 +8 而是 +805。
- 这种情况以 1901-01-01 为分界线。
查阅后发现,原来是市区变了:
1901-01-01 上海时区从 0805 调整成 0800。
当你把相同的时间转换为中国时间的时候,1901 年前会转换成 0805。这里的 43s 也和 sheet.js 中的 bug 对的上。只是又差了五分钟。