NodeJS 使用pg模块从questdb读取UTC时间戳,日期对象具有错误的UTC时间

k3fezbri  于 12个月前  发布在  Node.js
关注(0)|答案(3)|浏览(175)

questdb中的所有时间戳都是UTC时间,但是当我用nodejs questdb客户端读取它们时,它会给予我正确的时间,但是是我的本地时区。
例如,在数据库中存储了10:00 UTC的时间,当在nodejs中阅读这个时间时,我将获得10:00 GMT+0200(因此8:00 UTC)。
如何将时间读取为UTC/GMT+0200,以便获得正确的Date对象?
这是我当前从questdb读取数据的代码:

async getData(unitId: string) {
    const client = new Client([...]);
    await client.connect();
    const res = await client.query(
      `select Timestamp from 'myData' where ...`,
    );
    await client.end();
    return res.rows.map((x) => x?.Timestamp); // Timestamp is already an Date object with 10:00 GMT+0200
  }

编辑:
为了更清楚地说明我的问题:
数据库包含日期2023-09-26T06:18:56.740000Z。我只是在当地时间8:18保存了该条目,因为我位于GMT+0200,这是正确的UTC时间。

现在,当我想用上面的代码从数据库中获取这个条目时,我会得到一个日期,就像时间戳条目被读取为本地时间一样。这意味着它将采用06:18并将GMT+0200应用于它,使其成为06:18 GMT+0200。当我做Timestamp.toISOString()时,我会得到2023-09-26T04:18:56.740Z

ujv3wf0j

ujv3wf0j1#

JavaScript Date对象 * 始终 * 仅为UTC。它们是Unix时间戳的简单 Package 器,具有毫秒精度。您可以使用.valueOf().getTime()来查看时间戳,或者将其强制为数字类型(即+d)。
如果你的数据库在JS Date对象中返回UTC时间,那么它已经在做正确的事情了。
你展示的代码返回了Date对象,但是你没有展示你是如何使用这些对象的。您可能正在查看将Date对象强制转换为字符串以供显示的结果。例如,对.toString()的调用将使用计算机的本地时区将基于UTC的时间戳转换为本地时间,然后发出表示本地时间的字符串。相比之下,调用.toISOString().toUTCString()将发出一个表示UTC时间的字符串,而不进行任何转换。
值得注意的是(这通常是一个陷阱)-如果你console.log(someDateObject)-结果字符串可能是 either 本地时间或UTC时间,这取决于环境。ECMAScript规范和WhatWG控制台规范都没有定义它应该是什么,多年来不同的JavaScript实现选择了不同的方式。不记录Date对象,而是记录Date对象上的某个函数的字符串输出-例如.toISOString()(如果需要UTC)。

t5zmwmid

t5zmwmid2#

您所引用的代码片段使用pg库,因此您应该查看其文档,即数据类型页面:https://node-postgres.com/features/types
文件提到以下内容:
同样,当阅读datetimestamptimestamptz列值返回到JavaScript中时,node-postgres将把值解析为JavaScript Date对象的示例。
node-postgres将DATETIMESTAMP列转换为设置在process.env.TZ的节点进程的本地时间。
所以,这就是为什么你得到一个带有本地时区而不是UTC的Date
如果您不想弄乱环境变量,可以为timestamp类型定义一个自定义解析器。请查看https://github.com/brianc/node-pg-types中的示例以了解更多详细信息。
P.S.潜在的原因是Postgres假设timestamp time没有时区,而在QuestDB中它总是有UTC时区。我们以后会努力解决的。

vvppvyoh

vvppvyoh3#

我目前的一个快速解决方法是再次将时区添加到Date:

return res.rows?.map((x) => {
      x?.Timestamp.setTime(
        x.Timestamp.getTime() +
          x.Timestamp.getTimezoneOffset() * 60 * 1000 * -1,
      );
      return x.Timestamp;
    });

相关问题