前言
众所周知,mongoose的日期格式是ISODate,也就是使用的utc时间,举个栗子:
2020-12-11T16:00:00.000Z
,
T
表示分隔符,
Z
表示的是UTC。
UTC:世界标准时间,在标准时间上加上8小时,即东八区时间,也就是北京时间。
咱举个例子:
北京时间:
2020-12-12 00:00:00
对应的国际标准时间格式为:
2020-12-11T16:00:00.000Z
。
当我们的前端页面通过接口拿到我的utc时间后,一般通过new Date(时间),就能快速的转换成当地的时间。
这些周知的我就不再多举例了。
笔记原因
做这个笔记前,我遇到了时间进入到数据库没有准确的转换为utc,于是,好奇心驱使,我们开启mongoose的debug模式,来看看是什么实际mongoose到原生层的实际过程。
1 |
// 开启mongoose调试 |
举例,我有一个schema,里面有个updateDate,我们先来看看不同的日期插入数据库时候,实际的表现。
1 |
module.exports = (app) => { |
1 |
const deliver = await ctx.model.Delivery.File.create({ |
通过debug日志:
1 |
Mongoose: sys_files.insertOne({ isDel: false, _id: ObjectId("61b5599cba1fcfeeb79c57cd"), fileName: '文件名', uploadDate: new Date("Sat, 11 Dec 2021 16:00:00 GMT"), creatorName: '张三', __v: 0}, { session: null }) |
结论: `
我们发现mongoose的ORM层的
create
实际调用了
insertOne
,插入的本地时间
new Date("2021-12-12 00:00:00")
(
2021-12-11T16:00:00.000Z
)到达原生层变成了
Sat, 11 Dec 2021 16:00:00 GMT
并在进行了一次new Date(),
所以整个orm层到mongodb原生层的过程是这样的:
日期传入
->
(ORM)转换为GMT零时区
->
(ORM)new Date()转为ISODate
->
入库
new Date("2021-12-12 00:00:00")
传入 ->
2021-12-11T16:00:00.000Z
Sat, 11 Dec 2021 16:00:00 GMT
new Date("Sat, 11 Dec 2021 16:00:00 GMT")
->
2020-12-11T16:00:00.000Z
我们在拿一个字符串时间和moment时间对象来校验是不是这个过程:
日期传入
->
(ORM)转换为GMT零时区
->
(ORM)new Date()转为ISODate
->
入库
1 |
|
->
2021-12-12 00:00:00
传入
->(ORM)转换为GMT零时区
Sat, 11 Dec 2021 16:00:00 GMT
->(ORM)new Date()转为ISODate
new Date("Sat, 11 Dec 2021 16:00:00 GMT")
->
2020-12-11T16:00:00.000Z
->
入库
方式三:使用moment 插入
1 |
|
moment("2021-12-12 00:00:00")
传入 ->
Moment<2021-12-12T00:00:00+08:00>
Sat, 11 Dec 2021 16:00:00 GMT
new Date("Sat, 11 Dec 2021 16:00:00 GMT")
->
2020-12-11T16:00:00.000Z
others
我们发现当我们的时间只要是精确到时分秒,进入到mongodb数据库后,都能正确的转换成UTC时间。
那我们来试试 年月日的情况
1 |
const file = await ctx.model.Delivery.File.create({ |
结论: `
new Date('2021-12-12')
传入 ->
2021-12-12T00:00:00.000Z
(
注意此处年月日时间转换为UTC时间与上面带时分秒的差异
)
Sat, 11 Dec 2021 00:00:00 GMT
new Date("Sat, 11 Dec 2021 00:00:00 GMT")
->
2020-12-12T00:00:00.000Z
这也就解释了为什么本人在项目中传入
2021-12-12
的日期最终却变成了utc
2020-12-12T00:00:00.000Z
,也就是为什么new Date()本地时间会多出来8个小时的原因了。
mongoose这个ORM实际做了一步强制new Date()转换为utc时间。所以无论传入什么本地时间,都会强制转换mongodb所需要的ISODate时期格式。
所以无论是moment、dayjs等时间库的时间,最后都会被momgoose强制转换为new Date 的UTC时间。与用什么时间库或时间格式并无直接关系。
番外篇
我们来验证下查询的时候,传入的时间是不是也会通过mongoose自动强制new Date
验证发现流程:
Sat, 11 Dec 2021 00:00:00 GMT
new Date("Sat, 11 Dec 2021 00:00:00 GMT")
->
2020-12-12T00:00:00.000Z