sql >> Databasteknik >  >> RDS >> PostgreSQL

Knex konverterar tyst Postgres tidsstämplar med tidszon och returnerar felaktig tid

Förmodligen misslyckas saker eftersom när du frågar datumtider från databasen i en viss tidszon och effektivt konverterar typ av tidsstämpel till tidsstämpel utan tidszon. I så fall kommer databasen inte att skicka information till knex om i vilken tidszon den returnerade tiden var.

Så knex (eller snarare pg-drivrutinen som knex använder) tolkar din tidsstämpel som lokal tid, vilket beror på tidszonsinställningen för din applikationsserver som kör knex.

Du kan hämta tid precis som UTC och göra tidszonkonvertering på JavaScript-sidan med moment- eller luxon-bibliotek (IMO senare är bättre för tidszonshantering).

En annan lösning skulle vara att tala om för pg-drivrutinen att tidsstämpel och tidsstämpel med tidszontyper inte bör konverteras till JavaScript Date objekt.

Det kan göras så här (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);

Denna kod som gör att alla tidsstämplar ska returneras som strängar kan läggas till till exempel i början av knexfile.js . Dessa returnerade strängar kommer att vara exakt i samma format som de returnerades av databasservern själv.

EDIT:

I koden i det ursprungliga inlägget, när tidsstämpeln konverteras till att vara i tidszonen UTC databasserver konverterar timestamp with time zone typ för att vara normal timestamp without time zone så returnerat värde har ingen tidszonsinformation. För att lägga tillbaka tidszonsinformation kan du till exempel lägga till +02 i slutet av den returnerade tidsstämpeln så här:

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

Vilket returnerar 2010-01-01 00:00:00+00 till drivrutinen som också kan läsas korrekt av pg-drivrutinen.

Detta kommer att göra samma sak som att bara ställa in SET TIME ZONE 'UTC'; i db-servern när anslutningen skapas och bara returnerar timestamptz-kolumnen direkt:

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

Vilket returnerar 2009-12-31 22:00:00+00 .




  1. datetime-local värde visas inte på inmatningstaggen

  2. Selektiv import från CSV till MySQL

  3. hur man formaterar datum som kommer från MYSQL

  4. INSERT-satsen kom i konflikt med FOREIGN KEY-begränsningen - SQL Server