PostgreSQL
 sql >> Database >  >> RDS >> PostgreSQL

Knex converte silenziosamente i timestamp di Postgres con il fuso orario e restituisce l'ora errata

Probabilmente le cose stanno fallendo perché quando si interroga datetimes dal database in un determinato fuso orario e si converte efficacemente il tipo di timestamp in timestamp senza fuso orario. In tal caso, il database non invierà informazioni a knex sul fuso orario in cui si trovava l'ora restituita.

Quindi knex (o meglio il driver pg utilizzato da knex) interpreta il tuo timestamp come ora locale, che dipende dalla configurazione del fuso orario del tuo server delle applicazioni che esegue knex.

Puoi recuperare l'ora proprio come UTC ed eseguire la conversione del fuso orario sul lato JavaScript con le librerie moment o luxon (l'ultimo IMO è migliore per la gestione del fuso orario).

Un'altra soluzione sarebbe dire al driver pg che timestamp e timestamp con tipi di fuso orario non devono essere convertiti in JavaScript Date oggetti.

Può essere fatto in questo modo (https://github.com/brianc/node-pg- tipi ):

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

Questo codice che fa in modo che tutti i timestamp vengano restituiti come stringhe può essere aggiunto ad esempio all'inizio di knexfile.js . Quelle stringhe restituite saranno esattamente nello stesso formato in cui sono state restituite dal server di database stesso.

EDIT:

Nel codice nel post originale, quando il timestamp viene convertito nel fuso orario UTC il server del database converte timestamp with time zone digita per essere normale timestamp without time zone quindi il valore restituito non ha informazioni sul fuso orario. Per aggiungere le informazioni sul fuso orario, ad esempio, puoi aggiungere +02 alla fine del timestamp restituito in questo modo:

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

Che restituisce 2010-01-01 00:00:00+00 al driver che può essere letto correttamente anche dal driver pg.

Questo farà effettivamente la stessa cosa che basta impostare SET TIME ZONE 'UTC'; nel server db quando viene creata la connessione e restituisce direttamente la colonna timestamptz:

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

Che restituirà 2009-12-31 22:00:00+00 .