【问题标题】:Mongoose datetime and timezone, how to get datetime based on server timezoneMongoose 日期时间和时区,如何根据服务器时区获取日期时间
【发布时间】:2019-04-22 00:37:12
【问题描述】:

this问题的第一个答案表明猫鼬在检索数据时会根据服务器时区调整日期。

但是我没有这种行为。 我将(节点)服务器时区设置为: process.env.TZ='Europe/Paris'

例如,如果我创建一个简单的模型,例如:

const mongoose = require("mongoose");
const testSchema = new mongoose.Schema({
    myDate: { type: Date, required: true },
}, { timestamps: true });

exports.Comment = mongoose.default.model('TestSchema', testSchema); 

但是,如果我用2020-01-01 20:20:20 创建一个日期,那么在执行TestSchema.find() 时,日期将是:2020-01-01T19:20:20.000Z 所以有两件事我不明白:

  • 欧洲/巴黎实际上是 UTC +2,所以我希望日期是 UTC 中的 2020-01-01T18:20:20.000Z 或带有服务器时区的 2020-01-01T20:20:20.000Z
  • 如何让猫鼬自动将日期设置为正确的时区?

我知道 myDate 是一个 Date 对象,所以我可以手动转换它,但我宁愿不必自己做,原因很简单,比如忘记转换应用程序中的日期之一或不必做每次添加一个 Date 字段时它

我能想到的一个简单的解决方案是为 mongoose 注册一个全局插件,该插件将使用 schema.set('toJSON', ...schema.set('toObject', ...) 和 transform 方法,这样我就可以遍历 shema 字段,如果该字段是日期,则更新它到我的时区。 但我发现这种方法有两个问题:

  • 如果我要查询很多文档,每个文档都有很多字段,这听起来不太好
  • 如你所见here我目前无法注册全局插件...

以服务器时区格式获取日期的最佳方法是什么?我宁愿仍然将它们存储在 UTC 中,但根据服务器时区设置小时。

编辑:

我刚刚看到虽然console.log(myDate) 输出2018-01-01T19:20:20.000Z console.log(myDate.toString() 输出Mon Jan 01 2018 20:20:20 GMT+0100 (Central European Standard Time) 所以它似乎可以使用,即使我宁愿仍然有一个Date 对象并将其转换为字符串在将其发送给客户端之前(需要一些格式,因为这种格式不是非常用户友好)。但是话又说回来,我将如何在全球范围内而不是在每个日期都这样做

【问题讨论】:

    标签: node.js mongodb datetime mongoose timezone


    【解决方案1】:

    一些事情:

    • Europe/Paris2020-01-01T20:20:20 是 UTC+1。在 3 月 29 日夏令时开始之前,它不会切换到 UTC+2。 Reference here。因此转换为2020-01-01T19:20:20Z 是正确的。

    • console.log 在传递 Date 对象时的输出是特定于实现的。一些实现将发出.toString() 的输出(以RFC 2822 格式表示的当地时间),而一些实现将发出.toISOString() 的输出(以ISO 8601 扩展格式表示的UTC)。这就是您看到差异的原因。

    • 一般来说,发送本地时间而不发送时区偏移量是不好的。 ISO 8601 格式是理想的,但您应该发送2020-01-01T19:20:20Z2020-01-01T20:20:20+01:00。不要只向客户端发送没有偏移的日期和时间。否则,如果您的客户可能在不同的时区,那么他们会错误地解释该值。

    • 请记住,Date 对象是时区感知的。它们在内部仅包含一个 Unix 时间戳,并且它们仅转换为系统的本地时区以用于在本地时间工作的函数。它们不能在任何其他时区工作。

    • 依赖系统本地时区不利于可移植性。一个人并不总是有能力改变它,当你必须在多个时区工作时它也不会做得很好。 最好不要依赖从 Node 的 TZ 变量设置本地时区。相反,请考虑编写独立于任何本地时区设置的代码。

    • 时区感知日期库可以帮助您解决大部分问题。我可以推荐Luxonjs-JodaMoment + Moment-Timezonedate-fns + date-fns-timezone

    • “我将如何在全球范围内执行此操作”是我在您的问题中没有关注的内容。尝试我描述的方法,如果仍然有问题,请提出一个新问题。尝试具体并提出一个单个问题。这样你可能会得到更好的结果。请阅读How do I ask a good question?How to create a Minimal, Complete, and Verifiable example。谢谢。

    【讨论】:

    • 非常有趣。我对日期和时区的了解越多,这个主题就越复杂。请记住这是一个学校项目,但是我想遵循最佳实践如果我很好地理解了您的答案,我应该将 UTC 日期发送给客户,并且客户应该在显示之前对其进行调整?我为最后一点道歉,似乎“我将如何在全球范围内做到这一点”对于这个网站来说不是一个好问题
    • 所以基于用户时区转换日期的整个逻辑应该在客户端完成。看起来很合逻辑。你关于发送日期+时区的观点非常好
    猜你喜欢
    • 2013-05-19
    • 1970-01-01
    • 1970-01-01
    • 2014-11-10
    • 1970-01-01
    • 1970-01-01
    • 2013-07-13
    • 2014-04-21
    • 2020-10-19
    相关资源
    最近更新 更多