PG Promise 未正确返回 "timestamp with time zone" 字段

PG Promise not returning "timestamp with time zone" fields correctly

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

查询数据库
SELECT date FROM ro WHERE id = 13;

returns

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)
      })

returns

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

我期待的是

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

你 运行 psql 和 运行 pg-promise 在同一台机器上吗?

来自 timestamp with timezone

上的文档

For timestamp with time zone, the internally stored value is always in UTC (Universal Coordinated Time, traditionally known as Greenwich Mean Time, GMT). An input value that has an explicit time zone specified is converted to UTC using the appropriate offset for that time zone. If no time zone is stated in the input string, then it is assumed to be in the time zone indicated by the system's TimeZone parameter, and is converted to UTC using the offset for the timezone zone.

When a timestamp with time zone value is output, it is always converted from UTC to the current timezone zone, and displayed as local time in that zone. To see the time in another time zone, either change timezone or use the AT TIME ZONE construct (see Section 9.9.3).

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

The TimeZone configuration parameter can be set,

  1. in the file postgresql.conf
  2. In any of the other standard ways described in Chapter 19.
  3. The SQL command SET TIME ZONE sets the time zone for the session. This is an alternative spelling of SET TIMEZONE TO with a more SQL-spec-compatible syntax.
  4. The PGTZ environment variable is used by libpq clients to send a SET TIME ZONE command to the server upon connection.

所以你总是可以,

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();

您的 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.000Z.

如果您从该 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)