在 Mongoose 中,文档的 Date
类型默认使用 UTC 时间戳表示。这种时间戳是一个 Unix 时间戳的形式,它表示从 1970 年 1 月 1 日 00:00:00 UTC 开始到某个时间点的秒数。但是这种时间戳不太容易理解和直接使用,特别是需要转换成本地时间时,就需要使用一些技巧。
时间戳的解码
在 Mongoose 中,可以使用 toJSON()
方法来访问文档的 JSON 表现。这个方法会自动把 Date
类型转换成 ISO 8601 格式(例如:"2019-12-21T16:00:00.000Z")。这个格式非常常见,也容易转换成本地时间。但是,如果直接把一个包含时间戳的 JSON 对象传给前端,那么前端仍然需要手动解码时间戳。
解码时间戳的常用方式是使用 JavaScript 自带的 Date
对象。例如,可以使用下面的方式把一个 UTC 时间戳转换成本地时间:
const timestamp = 1576867200; // 时间戳对应 2019 年 12 月 21 日 16:00:00 const date = new Date(timestamp * 1000); const localDate = date.toLocaleString(); // 转换成本地时间字符串 console.log(localDate); // "2019-12-22 00:00:00"
但是这种方式有一个问题:它需要把时间戳乘以 1000,因为 JavaScript 的时间戳单位是毫秒而不是秒。这个转换可能容易被忽略或出错。因此,最好直接使用 Mongoose 提供的时间戳解码技巧。
Mongoose 提供了一个 toObject()
方法,它可以把文档转换成普通的 JavaScript 对象(而非 JSON 字符串)。如果在模式中设置了 { timestamps: true }
,则这个方法会自动添加两个字段 createdAt
和 updatedAt
,这两个字段的值就是对应文档的创建和更新时间戳。例如:
-- -------------------- ---- ------- ----- -------- - -------------------- ----- ------ - --- ----------------- ----- ------- -- - ----------- ---- --- ----- ----- - ----------------------- -------- ----- --- - --- ------- ----- ------ --- ---------------------------- -- - ---- ---- ----- ------- ---------- ----------- ---------- ---------- -
这个普通对象中的时间戳字段还是 UTC 时间戳,与 toJSON()
方法返回的结果相同。但是,Mongoose 提供了一个 toObject()
的选项,叫做 transform
。这个选项可以指定一个函数,用来转换对象的某个字段。使用这个选项,可以方便地把时间戳转换成本地时间。
下面是一个示例代码:
-- -------------------- ---- ------- ----- -------- - -------------------- ----- ------ - --- ----------------- ----- ------- -- - ----------- ---- --- ---------------------- - ---------- ----- ---- -------- -- - -- --------------- - ------------- - --- ------------------ - ----------------------- - -- --------------- - ------------- - --- ------------------ - ----------------------- - ------ ---- -- --- ----- ----- - ----------------------- -------- ----- --- - --- ------- ----- ------ --- ---------------------------- -- - ---- ---- ----- ------- ---------- ----------- ---------- ---------- ----------- --------- -
在这个示例代码中,我们通过 schema.set()
方法设置了 toObject
选项,并且指定了一个转换函数。这个函数会遍历对象的所有属性,如果发现一个名为 createdAt
或 updatedAt
的属性,则把它转换成本地时间格式。最后,这个函数返回转换后的对象。
有了这个技巧,我们就可以方便地在后端中解码时间戳,而且可以直接把转换后的对象传给前端,避免了前端重复解码的问题。
总结
Mongoose 中使用 UTC 时间戳表示文档中的时间字段,可以使用 toJSON()
方法来访问 JSON 表现,也可以使用 toObject()
方法来访问 JavaScript 对象。使用 transform
选项可以方便地转换对象的某个字段,例如把时间戳转换成本地时间格式。这个技巧可以避免时间戳单位转换的问题,也可以避免前端重复解码的问题。
来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/64d4bc77b5eee0b525c8fa5a