sql >> Base de Datos >  >> RDS >> PostgreSQL

Knex convierte silenciosamente las marcas de tiempo de Postgres con la zona horaria y devuelve una hora incorrecta

Probablemente, las cosas están fallando porque cuando consulta fechas y horas de la base de datos en cierta zona horaria y convierte efectivamente el tipo de marca de tiempo en una marca de tiempo sin zona horaria. En ese caso, la base de datos no enviará información a knex sobre en qué zona horaria estaba la hora devuelta.

Entonces, knex (o más bien el controlador pg que está usando knex) interpreta su marca de tiempo como la hora local, que depende de la configuración de la zona horaria de su servidor de aplicaciones que ejecuta knex.

Puede obtener la hora como UTC y hacer la conversión de la zona horaria en el lado de JavaScript con las bibliotecas moment o luxon (IMO última es mejor para el manejo de la zona horaria).

Otra solución sería decirle al controlador pg que la marca de tiempo y la marca de tiempo con tipos de zona horaria no deben convertirse a JavaScript Date objetos.

Se puede hacer así (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 hace que todas las marcas de tiempo se devuelvan como cadenas se puede agregar, por ejemplo, al inicio de knexfile.js . Esas cadenas devueltas estarán exactamente en el mismo formato que fueron devueltas por el propio servidor de la base de datos.

EDITAR:

En el código de la publicación original, cuando la marca de tiempo se convierte para estar en la zona horaria UTC servidor de base de datos convierte timestamp with time zone tipo para ser normal timestamp without time zone por lo que el valor devuelto no tiene información de zona horaria. Para volver a agregar la información de la zona horaria, puede, por ejemplo, agregar +02 al final de la marca de tiempo devuelta de esta manera:

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

Que devuelve 2010-01-01 00:00:00+00 al controlador que también puede ser leído correctamente por el controlador pg.

Esto hará efectivamente lo mismo que configurar SET TIME ZONE 'UTC'; en el servidor db cuando se crea la conexión y solo devuelve la columna timestamptz directamente:

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

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