webdevqa.jp.net

node-postgresを使用して、UTCで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_を表す日付オブジェクト(または文字列)です。私はすでにknow今回はUTCです。

Postgresql.confファイルのタイムゾーンパラメータを_timezone = 'UTC'_に設定しようとしましたが、結果に違いはありません。

私は何が間違っているのですか?

[〜#〜]編集[〜#〜]

問題はこのファイルにあるようです: https://github.com/brianc/node-postgres/blob/master/lib/types/textParsers.js

Postgresから返された日付文字列にタイムゾーンが指定されていない場合(つまり、Zまたは_+06:30_)、JavaScriptの日付オブジェクトを作成するだけです。これには現地時間が含まれると思います。ゾーン。DBにタイムゾーンを保存するようにアプリを変更するか、このコンバーターをオーバーライドする必要があります。

14

古い質問を復活させるためではありませんが、まったく同じ問題が発生したことを確認すると、 ここtimestamp without time zoneに使用する型パーサーをオーバーライドすることで機能する代替ソリューションがあります。

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

これにより、node-pgが値をDateオブジェクトに解析するのを防ぎ、代わりに生のタイムスタンプ文字列を提供します。

出典: node-postgresの問題 から入手

17

@BadIdeaExceptionが示唆するように、パーサーを変更できます。以下は、それが期待どおりに機能しない理由の詳細と、2つの可能な解決策です。

タイプがtimestamp without time zoneの列の場合、パーサーはタイムゾーンが指定されていないISO8601形式の文字列を受け取ります。2016-07-12 22:47:34

JavascriptでDateオブジェクトを作成するときはいつでも、タイムゾーンを指定しないと、日付が現在のタイムゾーンにあると見なされます。定義上GMTタイムゾーンにあるUTC日付の場合、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()は、オブジェクトではなく日付valueを返すことに注意してください。これは、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())
    );
}
6
stone

これは最善の解決策ではありませんが、Postgresタイプを使用するように切り替えましたtimestamp with time zoneそして私がDBに固執したすべての日付がUTCであることを確認しました。