Node应用向MongoDB插入时间戳时Date类型与本地时区时间不符问题
问题根因
- JavaScript 原生
Date对象、MongoDB 内置的日期类型,底层存储的都是不带时区的Unix时间戳(毫秒值),你看到的2021-09-16T11:32:33.000Z是UTC 0时区的标准显示格式,和你预期的2021-09-16T13:32:33+02:00是完全相同的时间点,只是显示时区不同,存储本身没有错误。 - 西班牙时区夏令时为UTC+2,冬令时为UTC+1,所以UTC时间加对应偏移量就是你要的本地时间。
推荐解决方案
方案1:仅在查询展示时转换时区(最优)
保留MongoDB原生日期类型的存储方式,不改动插入逻辑,仅在数据查询出来后转换为西班牙本地时间展示,不会失去MongoDB针对日期类型的范围查询、聚合计算能力。
需要给dayjs安装时区扩展插件,示例代码如下:
// 安装依赖:npm install dayjs dayjs-plugin-utc dayjs-plugin-timezone const dayjs = require('dayjs') const utc = require('dayjs/plugin/utc') const timezone = require('dayjs/plugin/timezone') dayjs.extend(utc) dayjs.extend(timezone) // 从MongoDB查询到的日期对象直接转西班牙时区 const localDate = dayjs(mongoQueryResult.create_time).tz('Europe/Madrid').format() // 输出:2021-09-16T13:32:33+02:00
如果想要全局生效不需要每次转换,可以在启动Node服务时指定时区环境变量:
TZ=Europe/Madrid node your-app.js
方案2:存储时同时保存日期类型和本地字符串(适配特殊展示需求)
如果你的业务需要直接从数据库拿到格式化的本地时间,可以分两个字段存储:
const rawTimestamp = data.channels.timestamp * 1000 const insertData = { // 原生日期类型,用于MongoDB的时间查询、聚合运算 timestamp: new Date(rawTimestamp), // 格式化的西班牙本地时间字符串,直接用于展示 timestamp_local: dayjs(rawTimestamp).tz('Europe/Madrid').format() } // 直接将insertData插入MongoDB即可
验证方式
你可以对比原始时间戳和转换后的Date对象的时间戳,确认时间没有偏差:
const rawTs = data.channels.timestamp * 1000 const dateObj = new Date(dayjs(rawTs).format()) console.log(rawTs === dateObj.getTime()) // 输出为true,说明时间完全一致
内容的提问来源于stack exchange,提问作者Alejandro
相关产品推荐
相关产品推荐

