我有一些时间戳存储为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 param设置为:timezone = 'UTC'
,结果没有区别.
我究竟做错了什么?
编辑
问题似乎出现在这个文件中:https://github.com/brianc/node-postgres/blob/master/lib/types/textParsers.js
如果从Postgres返回的日期字符串没有指定时区(Z
或者+06:30
,那么它只是构造一个JavaScript日期对象,我相信它只包含本地时区.我要么将我的应用程序更改为存储DB中的时区或覆盖此转换器.
不是为了重新回答一个旧问题,而是看到我在这里遇到了完全相同的问题,还有一种替代解决方案可以通过覆盖类型解析器来实现timestamp without time zone
:
var pg = require('pg'); var types = pg.types; types.setTypeParser(1114, function(stringValue) { return stringValue; });
这将使node-pg不会将值解析为Date
对象,而是为您提供原始时间戳字符串.
来源:从node-postgres问题得到它
您可以按照@BadIdeaException的建议修改解析器。以下是有关为何无法按预期运行的更多详细信息,以及两种可能的解决方案。
对于type为的列timestamp without time zone
,解析器将接收ISO 8601格式的字符串,未指定时区:2016-07-12 22:47:34
任何时候在Javascript中创建Date对象时,如果未指定时区,则会假定该日期在当前时区中。对于UTC日期(根据定义,该日期位于GMT时区),除非您的Javascript恰巧在GMT时区中运行,否则它将为您提供一个具有不正确的绝对值(date.value)的日期。
因此,该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()) ); }