PostgreSQL
 sql >> Datenbank >  >> RDS >> PostgreSQL

Knex konvertiert Postgres-Zeitstempel im Hintergrund mit der Zeitzone und gibt eine falsche Zeit zurück

Wahrscheinlich schlagen die Dinge fehl, weil Sie Datetimes aus der Datenbank in einer bestimmten Zeitzone abfragen und den Typ des Zeitstempels effektiv in einen Zeitstempel ohne Zeitzone konvertieren. In diesem Fall sendet die Datenbank keine Informationen darüber, in welcher Zeitzone die zurückgegebene Zeit lag, an knex.

Knex (oder besser gesagt der pg-Treiber, den Knex verwendet) interpretiert Ihren Zeitstempel als Ortszeit, was von der Zeitzoneneinstellung Ihres Anwendungsservers abhängt, auf dem Knex ausgeführt wird.

Sie könnten die Zeit genauso wie UTC abrufen und die Zeitzonenkonvertierung auf der JavaScript-Seite mit Moment- oder Luxon-Bibliotheken durchführen (letzteres ist meiner Meinung nach besser für die Zeitzonenbehandlung).

Eine andere Lösung wäre, dem pg-Treiber mitzuteilen, dass Zeitstempel und Zeitstempel mit Zeitzonentypen nicht in JavaScript konvertiert werden sollen Date Objekte.

Es kann so gemacht werden (https://github.com/brianc/node-pg- Typen ):

const types = require('pg').types;
const TIMESTAMPTZ_OID = 1184;
const TIMESTAMP_OID = 1114;
types.setTypeParser(TIMESTAMPTZ_OID, val => val);
types.setTypeParser(TIMESTAMP_OID, val => val);

Dieser Code, der dafür sorgt, dass alle Zeitstempel als Strings zurückgegeben werden, kann zum Beispiel am Anfang von knexfile.js hinzugefügt werden . Diese zurückgegebenen Zeichenfolgen haben genau das gleiche Format, in dem sie vom Datenbankserver selbst zurückgegeben wurden.

BEARBEITEN:

Im Code im ursprünglichen Beitrag, wenn der Zeitstempel in die Zeitzone UTC konvertiert wird Datenbankserver konvertiert timestamp with time zone Geben Sie den normalen timestamp without time zone ein Der zurückgegebene Wert enthält also keine Zeitzoneninformationen. Um Zeitzoneninformationen wieder hinzuzufügen, können Sie beispielsweise +02 wie folgt an das Ende des zurückgegebenen Zeitstempels anhängen:

select ('2010-01-01T00:00:00.000Z'::timestamptz AT TIME ZONE 'UTC')::text || '+00';

Was 2010-01-01 00:00:00+00 zurückgibt zum Treiber, der auch vom pg-Treiber korrekt gelesen werden kann.

Dies wird effektiv das Gleiche bewirken wie das einfache Setzen von SET TIME ZONE 'UTC'; im DB-Server, wenn die Verbindung hergestellt wird und nur die Timestamptz-Spalte direkt zurückgibt:

SET TIME ZONE 'UTC';
select '2010-01-01T00:00:00.000+02:00'::timestamptz;

Was 2009-12-31 22:00:00+00 zurückgibt .