sql >> Databáze >  >> RDS >> PostgreSQL

Knex tiše převádí časová razítka Postgres s časovým pásmem a vrací nesprávný čas

Pravděpodobně věci selhávají, protože když se dotazujete na datum a čas z databáze v určitém časovém pásmu a efektivně převádíte typ časového razítka na časové razítko bez časového pásma. V takovém případě databáze nepošle informace knexu o tom, ve kterém časovém pásmu byl vrácený čas.

Takže knex (nebo spíše ovladač pg, který knex používá) interpretuje vaše časové razítko jako místní čas, což závisí na nastavení časového pásma vašeho aplikačního serveru, na kterém běží knex.

Můžete načíst čas stejně jako UTC a provést konverzi časového pásma na straně JavaScriptu pomocí knihoven momentů nebo luxonů (IMO druhý je lepší pro zpracování časového pásma).

Dalším řešením by bylo sdělit ovladači pg, že časové razítko a časové razítko s typy časového pásma by neměly být převedeny na JavaScript Date objektů.

Lze to udělat takto (https://github.com/brianc/node-pg- typy ):

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

Tento kód, díky kterému budou všechna časová razítka vrácena jako řetězce, lze přidat například na začátek knexfile.js . Tyto vrácené řetězce budou přesně ve stejném formátu, v jakém byly vráceny samotným databázovým serverem.

EDIT:

V kódu v původním příspěvku, když je časové razítko převedeno na časové pásmo UTC databázový server převádí timestamp with time zone zadejte jako normální timestamp without time zone takže vrácená hodnota nemá informace o časovém pásmu. Chcete-li přidat informace o časovém pásmu zpět, můžete například přidat +02 na konec vráceného časového razítka takto:

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

Což vrátí 2010-01-01 00:00:00+00 na ovladač, který může být správně načten také ovladačem pg.

To bude v podstatě dělat totéž, co pouze nastavení SET TIME ZONE 'UTC'; v db serveru, když je vytvořeno připojení a přímo vrací sloupec timestamptz:

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

Což vrátí 2009-12-31 22:00:00+00 .




  1. Dotaz UPDATE nefunguje s LIMIT

  2. Rozdíl mezi JOIN a INNER JOIN

  3. REPLACE pro MySQL bez ohledu na velikost písmen

  4. Mysql High UPDATE SELECT způsobuje zpoždění