2

我正在使用pg-promise lib 来处理 Postgres DB。我不明白为什么直接查询数据库

SELECT date FROM ro WHERE id = 13;

返回

date          
------------------------
 2017-01-19 00:00:00+02
(1 row)

这个 pgp 调用:

var sql = 'SELECT date from ro WHERE id = 1366';
    Dbh.odb.any(sql)
      .then(ro => {
        console.log(ro);
        res.ok(ro)
      })

返回

{
    "date": "2017-01-18T22:00:00.000Z"
}

我期望的是

{
   "date": "2017-01-19T00:00:00.000Z"
}
4

2 回答 2

3

psql是否在运行 pg-promise 的同一台机器上运行?

从文档开始timestamp with timezone

对于带时区的时间戳,内部存储的值始终采用 UTC(通用协调时间,传统上称为格林威治标准时间,GMT)。使用该时区的适当偏移量将具有指定明确时区的输入值转换为 UTC。如果输入字符串中没有说明时区,则假定它位于系统的TimeZone 参数指示的时区中,并使用时区的偏移量转换为 UTC。

当输出带有时区值的时间戳时,它总是从 UTC 转换为当前时区,并显示为该时区的本地时间。要查看另一个时区的时间,要么更改时区,要么使用AT TIME ZONE构造(参见第 9.9.3 节)。

因此时区存储在 UTC 中,并根据TimeZone参数从该文档中检索(稍微清理)

TimeZone可以设置配置参数,

  1. 在文件 postgresql.conf 中
  2. 第 19 章中描述的任何其他标准方式。
  3. SQL 命令 SET TIME ZONE 设置会话的时区。这是 SET TIMEZONE TO 的另一种拼写,具有更符合 SQL 规范的语法。
  4. libpq 客户端使用 PGTZ 环境变量在连接时向服务器发送 SET TIME ZONE 命令。

所以你总是可以,

var sql = `SELECT date AT TIME ZONE '+02' from ro WHERE id = 1366`;
    Dbh.odb.any(sql)
      .then(ro => {
        console.log(ro);
        res.ok(ro)
      })

或者为客户端、会话或服务器设置时区。

timezone您可以在这里找到潜在价值

SELECT * FROM pg_timezone_names();
于 2017-01-12T20:41:32.917 回答
2

您的psql输出显示您拥有的时间戳是在午夜,但在 UTC+2 时区 (2017-01-19 00:00:00+ 02 ),比 UTC 早两个小时。

也就是说,当时间是 UTC+2 的 00:00:00 时,它只是 UTC 的前一天 22:00:00 - 这就是你得到的: 2017-01- 18T22 :00:00.000 Z

如果您从该 UTC 日期创建一个 JavaScript 日期,如果您在 UTC+2 上,您将获得午夜。这是我在 UTC+2 的 Chrome 控制台中看到的内容:

new Date('2017-01-18T22:00:00.000Z');
Thu Jan 19 2017 00:00:00 GMT+0200 (EET)

如果您真的希望将时间戳存储为午夜 UTC,您应该在插入日期时定义时区。但是请注意,UTC+2 不会是午夜:

new Date('2017-01-19T00:00:00.000Z');
Thu Jan 19 2017 02:00:00 GMT+0200 (EET)
于 2017-01-12T20:53:10.153 回答