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

Knex konverterer stille Postgres-tidsstempler med tidszone og returnerer forkert tid

Sandsynligvis fejler tingene, fordi når du forespørger om dato og klokkeslæt fra databasen i en bestemt tidszone og effektivt konverterer typen af ​​tidsstempel til at være tidsstempel uden tidszone. I så fald vil databasen ikke sende information til knex om, i hvilken tidszone den returnerede tid var.

Så knex (eller rettere pg-driver, som knex bruger) fortolker dit tidsstempel som lokal tid, hvilket afhænger af tidszoneopsætningen af ​​din applikationsserver, der kører knex.

Du kan hente tid lige som UTC og udføre tidszonekonvertering i JavaScript-siden med moment- eller luxon-biblioteker (IMO sidstnævnte er bedre til tidszonehåndtering).

En anden løsning ville være at fortælle pg-driveren, at tidsstempel og tidsstempel med tidszonetyper ikke bør konverteres til JavaScript Date genstande.

Det kan gøres sådan (https://github.com/brianc/node-pg- typer ):

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

Denne kode, der gør, at alle tidsstempler skal returneres som strenge, kan f.eks. tilføjes i starten af ​​knexfile.js . Disse returnerede strenge vil være nøjagtigt i det samme format, som de blev returneret af databaseserveren selv.

EDIT:

I kode i det originale indlæg, når tidsstemplet konverteres til at være i tidszonen UTC databaseserver konverterer timestamp with time zone type for at være normal timestamp without time zone så returneret værdi har ikke tidszoneoplysninger. For at tilføje tidszoneoplysninger tilbage kan du f.eks. tilføje +02 til slutningen af ​​returneret tidsstempel på denne måde:

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

Hvilket returnerer 2010-01-01 00:00:00+00 til driveren, som også kan læses korrekt af pg-driveren.

Dette vil i praksis gøre det samme som bare at indstille SET TIME ZONE 'UTC'; i db-serveren, når forbindelsen er oprettet og bare returnerer timestamptz-kolonnen direkte:

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

Hvilket returnerer 2009-12-31 22:00:00+00 .




  1. Variable får NULL efter beregninger i MySQL Trigger

  2. Gendannelse af en mySQL-instans fra en anden brugerkonto (macOS)

  3. Django-enhedstest mislykkedes for flere Postgres-skemaer

  4. Opret en unik begrænsning med null-kolonner