【问题标题】:NodeJS: Why is there a two hour difference in new Date()?NodeJS:为什么 new Date() 有两个小时的差异?
【发布时间】:2019-02-07 15:38:33
【问题描述】:

我在做一个

console.log(process.env.TZ);
console.log(new Date());

输出

Europe/Amsterdam
2018-09-02T08:07:03.842Z

但当前时间是 10:07 而不是 08:07。

实际的问题是,当我将模型保存到数据库时,它会以某种方式转换为 UTC,这不是我想要的。它就像 order.delivery_date = 2018-08-06 10:00:00;订单.保存()。当我查看数据库时,它显示 08:00:00。我该如何防止这种情况发生?

我正在使用 Loopback 3 和 MySQL。

【问题讨论】:

  • “UTC 这不是我想要的”是的。
  • 许多答案已经发布。您能否详细说明您的问题没有得到完整回答?
  • new Date().toLocaleTimeString()new Date().toLocaleDateString() 怎么样?
  • 为了克服服务器和浏览器之间的时区差异,我总是选择将 db-timezone 设置配置为 UTC (GMT 0) 。使用 .toISOString() 使用 JS 日期将数据从服务器插入数据库。并使用 .toLocaleString() 将值呈现给用户。这样,服务器和数据库使用相同的语言,浏览器使用用户语言。

标签: javascript node.js date loopbackjs utc


【解决方案1】:

输出

Europe/Amsterdam
2018-09-02T08:07:03.842Z

但当前时间是 10:07 而不是 08:07。

字符串上的Z 表示时间是UTC,而不是本地时间。这只是 Node.js 控制台在您传递一个字符串时输出的字符串(它来自toUTCString)。 JavaScript Date 对象在本地时间工作,但也具有访问 UTC 时间的功能(getUTCHoursgetUTCMinutes 等); toUTCString 就是其中之一。

您可以在Date 对象(getHoursgetMinutes 等)上使用各种本地时间函数,并从中获取本地时间信息。 (例如,toString 可能会给你一个本地时间字符串。)

【讨论】:

  • 感谢您的澄清。那么,如何确保在保存日期时,它完全按照我输入的方式保存呢? customer.login_time = 2018-08-15 10:30:30;customer.save() 存储为 customer.login_time = 2018-08-15 08:30:30;
  • @apfz 只需存储为 UTC 并以本地时间显示。这确保了时间的意义对于任何查看它的人来说都是有意义的。
  • @apfz - 您如何处理应用程序中的日期取决于您使用它们的目的。在许多情况下,正如 Patrick 所说,存储 UTC 并转换为您需要的任何时区是一个不错的选择。但这真的取决于情况。
  • 这些日期将仅在我的国家(仅 1 个时区)使用,并且也用于跨应用程序。对我来说,最好按照我输入的方式存储日期。所以我正在寻找一种解决方案,我可以将其存储在我当地的时区。
  • @apfz - 所以...这样做(尽管坦率地说,这听起来不太适合未来)。正如我上面所说,Date 对象提供本地时间访问器。
【解决方案2】:

我没有您设置的完整图片,但是是的,在保存日期时,环回确实会从本地时间转换为 UTC。如果您查看 mysql 连接器,您会发现以下函数根据给定日期的 UTC 值构建 datetime 字符串:

function dateToMysql(val) {
  return val.getUTCFullYear() + '-' +
    fillZeros(val.getUTCMonth() + 1) + '-' +
    fillZeros(val.getUTCDate()) + ' ' +
    fillZeros(val.getUTCHours()) + ':' +
    fillZeros(val.getUTCMinutes()) + ':' +
    fillZeros(val.getUTCSeconds());

  function fillZeros(v) {
    return v < 10 ? '0' + v : v;
  }
}

但是,它应该在加载时将日期恢复为本地时间,因为它会从存储的字符串中初始化 javascript Date 对象,该对象将转换为本地时间:

val = new Date(val.toString().replace(/GMT.*$/, 'GMT'));

您最好的选择可能是使用operation hooks 并在数据流入/流出模型时对其进行操作。例如,当数据从数据存储中加载时,您可以根据需要格式化日期:

Order.observe("loaded", (ctx, next) => {
    if (ctx.data) {
      ctx.data.delivery_date_formatted = tzFormat(ctx.data.delivery_date);
    }

    next();
  });

您还可以从另一个方向处理此问题,并操作正在持久化的数据。您不能真正阻止环回将日期存储为 UTC,但您可以添加或删除时区偏移量,因此一旦它被环回连接器剥离,它将与您的本地时间保持一个字符串(非常 hacky,我不会推荐它)。示例:

Order.observe("before save", (ctx, next) => {
    if (ctx.instance) {
      ctx.instance.delivery_date = new Date(
        Date.UTC(
          ctx.instance.delivery_date.getFullYear(),
          ctx.instance.delivery_date.getMonth(),
          ctx.instance.delivery_date.getDate(),
          ctx.instance.delivery_date.getHours(),
          ctx.instance.delivery_date.getMinutes(),
          ctx.instance.delivery_date.getSeconds()
        )
      );
    }

    next();
  });

【讨论】:

    【解决方案3】:

    回答标题问题: new Date() 将返回 UTC 时间值,在字符串末尾有 Z 时区指示符和时区值(在您的情况下为 2)。

    回答关于 db save() 调用的问题: 这取决于您的数据访问层和数据列类型。

    可能有两种主要方法:

    • 保存 UTC 并显示本地时间(因为您将拥有 2 个以上时区的用户)

    所以你的save() 可以正常工作,你应该只添加一个本地时间转换器(通常最好的方法是在前端添加它)

    • 按原样保存本地时间的值(不推荐,但可能有用)

    因此,您应该在写入/读取时进行转换器或更改列的类型,使其不应该使用 UTC 格式(例如,一种简单但很老套的方法是将其存储为字符串值)

    如果您选择使用转换器的方式,我建议您使用moment.js(无论是前端还是后端)。当您需要任何时间操作时,它可以节省时间,但可能会产生开销。

    您也可以手动制作(例如,减少捆绑包大小),您可以使用this 答案中的方法:

    const options = {
        timeZone: "America/New_York",
        year: 'numeric', month: 'numeric', day: 'numeric',
        hour: 'numeric', minute: 'numeric', second: 'numeric'
    };
    
    const formatter = new Intl.DateTimeFormat([], options);
    
    const UTCTime = "2017-09-03T02:00:00Z";
    const localTime = formatter.format(new Date(UTCTime));
    const currentTime = formatter.format(new Date()); 
    console.log(currentTime, localTime);
    

    【讨论】:

      猜你喜欢
      • 2017-06-18
      • 1970-01-01
      • 2021-12-03
      • 2014-11-26
      • 2016-07-03
      • 1970-01-01
      • 2017-11-27
      • 2018-08-26
      • 1970-01-01
      相关资源
      最近更新 更多