PostgreSQL
 sql >> Base de Dados >  >> RDS >> PostgreSQL

O Knex converte silenciosamente os carimbos de data e hora do Postgres com fuso horário e retorna a hora incorreta


Provavelmente as coisas estão falhando porque quando você está consultando datas do banco de dados em determinado fuso horário e convertendo efetivamente o tipo de carimbo de data/hora para ser carimbo de data/hora sem fuso horário. Nesse caso, o banco de dados não enviará informações ao knex sobre em qual fuso horário o horário retornado estava.

Portanto, o knex (ou melhor, o driver pg que o knex está usando) interpreta seu registro de data e hora como hora local, que depende da configuração do fuso horário do seu servidor de aplicativos executando o knex.

Você pode buscar o tempo como UTC e fazer a conversão do fuso horário no lado do JavaScript com bibliotecas moment ou luxon (o IMO é melhor para o manuseio do fuso horário).

Outra solução seria dizer ao driver pg que timestamp e timestamp com tipos de fuso horário não devem ser convertidos em JavaScript Date objetos.

Isso pode ser feito assim (https://github.com/brianc/node-pg- tipos ):
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);

Este código que faz com que todos os timestamps sejam retornados como strings podem ser adicionados, por exemplo, no início de knexfile.js . Essas strings retornadas estarão exatamente no mesmo formato em que foram retornadas pelo próprio servidor de banco de dados.

EDITAR:

No código da postagem original, quando o carimbo de data/hora é convertido para o fuso horário UTC servidor de banco de dados converte timestamp with time zone tipo para ser normal timestamp without time zone então o valor retornado não tem informações de fuso horário. Para adicionar informações de fuso horário de volta, você pode, por exemplo, anexar +02 ao final do carimbo de hora retornado assim:
select ('2010-01-01T00:00:00.000Z'::timestamptz AT TIME ZONE 'UTC')::text || '+00';

Que retorna 2010-01-01 00:00:00+00 para o driver que também pode ser lido corretamente pelo driver pg.

Isso fará efetivamente a mesma coisa que apenas definir SET TIME ZONE 'UTC'; no servidor db quando a conexão é criada e apenas retornando a coluna timestamptz diretamente:
SET TIME ZONE 'UTC';
select '2010-01-01T00:00:00.000+02:00'::timestamptz;

Que retornará 2009-12-31 22:00:00+00 .