使用node-postgres在utc中获取Postgres“没有时区的时间戳”

时间:2013-12-20 21:34:48

标签: node.js postgresql node-postgres

我有一些时间戳存储为Postgres类型timestamp without time zone

我将使用时间戳2013-12-20 20:45:27作为示例。我打算这代表一个UTC时间戳。

在psql中,如果我运行查询SELECT start_time FROM table_name WHERE id = 1,我会按预期返回该时间戳字符串:2013-12-20 20:45:27

但是,如果在我的Node应用程序中,我使用node-postgres库来运行相同的查询,我会在本地时区获取时间戳:Fri Dec 20 2013 20:45:27 GMT-0600 (CST)。这是一个Javascript日期对象,但它已经存储为该时区。我真正想要的是一个代表2013-12-20 20:45:27 GMT+0000的日期对象(甚至只是一个字符串)。我已经知道这次是UTC。

我已经尝试将postgresql.conf文件中的时区参数设置为:timezone = 'UTC',结果没有区别。

我做错了什么?

修改

问题似乎出现在此文件中:https://github.com/brianc/node-postgres/blob/master/lib/types/textParsers.js

如果从Postgres返回的日期字符串没有指定时区(即Z+06:30,那么它只构建一个JavaScript日期对象,我相信它只包括本地时区。我需要更改我的应用程序以在DB中存储时区或覆盖此转换器。

4 个答案:

答案 0 :(得分:16)

不是为了重振一个旧问题,而是看到我刚刚遇到完全相同的问题here,有一个替代解决方案可以通过覆盖用于timestamp without time zone的类型解析器来实现:

var pg = require('pg');
var types = pg.types;
types.setTypeParser(1114, function(stringValue) {
return stringValue;
});

这将使node-pg不会将值解析为Date对象,而是为您提供原始时间戳字符串。

来源:来自node-postgres issues

答案 1 :(得分:3)

这不是最好的解决方案,但我刚刚切换到使用Postgres类型timestamp with time zone并确保我持久保存到数据库的所有日期都是UTC。

答案 2 :(得分:3)

您可以修改解析器,如@BadIdeaException所示。以下是有关它为什么没有按预期工作的更多细节,以及两种可能的解决方案。

对于类型为timestamp without time zone的列,解析器会收到ISO 8601格式的字符串,但未指定时区:2016-07-12 22:47:34

每次在Javascript中创建Date对象时,如果未指定时区,则假定日期位于当前时区。对于UTC日期,根据定义属于GMT时区,这将为您提供不正确的绝对值(date.value)的日期,除非您的Javascript恰好在GMT时区中运行

因此, ISO 8601字符串不能由Date构造函数直接转换为UTC日期。您可以选择:修改字符串,使其解释为UTC:

var pg = require('pg');
var types = pg.types;
types.setTypeParser(1114, function(stringValue) {
    return new Date(stringValue + "+0000");
});

或者使用"错误"创建日期。 (当前)时区,然后提取它的值(仍在当前时区),然后使用这些值在UTC时区生成日期。请注意,Date.UTC()返回日期而不是对象,然后可以将其传递给Date构造函数。

types.setTypeParser(1114, function(stringValue) {

    var temp = new Date(stringValue);
    return new Date(Date.UTC(
        temp.getFullYear(), temp.getMonth(), temp.getHours(), temp.getMinutes(), temp.getSeconds(), temp.getMilliseconds())
    );
}

答案 3 :(得分:0)

我想知道@BadIdeaException是从哪里获得数字1114的。 在打字稿中,可以从界面看到值。

import { types } from 'pg';
types.setTypeParser(types.TypeId.TIME, (timeStr) => timeStr);
types.setTypeParser(types.TypeId.TIMESTAMP, (timeStr) => timeStr);
types.setTypeParser(types.TypeId.TIMESTAMPTZ, (timeStr) => timeStr);

这将覆盖所有时间戳字段解析器,并防止将字段错误地解析为Date对象。