PostgreSQL
 sql >> Base de données >  >> RDS >> PostgreSQL

Knex convertit silencieusement les horodatages Postgres avec le fuseau horaire et renvoie une heure incorrecte

Les choses échouent probablement parce que lorsque vous interrogez les dates-heures de la base de données dans un certain fuseau horaire et que vous convertissez efficacement le type d'horodatage en horodatage sans fuseau horaire. Dans ce cas, la base de données n'enverra pas d'informations à knex sur le fuseau horaire dans lequel se trouvait l'heure renvoyée.

Ainsi, knex (ou plutôt le pilote pg utilisé par knex) interprète votre horodatage comme l'heure locale, qui dépend de la configuration du fuseau horaire de votre serveur d'application exécutant knex.

Vous pouvez récupérer l'heure juste comme UTC et effectuer la conversion du fuseau horaire côté JavaScript avec les bibliothèques moment ou luxon (la dernière IMO est meilleure pour la gestion du fuseau horaire).

Une autre solution serait de dire au pilote pg que l'horodatage et l'horodatage avec des types de fuseau horaire ne doivent pas être convertis en JavaScript Date objets.

Cela peut être fait comme ceci (https://github.com/brianc/node-pg- types ):

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

Ce code qui rend tous les horodatages à renvoyer sous forme de chaînes peut être ajouté par exemple au début de knexfile.js . Ces chaînes renvoyées seront exactement dans le même format qu'elles ont été renvoyées par le serveur de base de données lui-même.

MODIFIER :

Dans le code du message d'origine, lorsque l'horodatage est converti pour être dans le fuseau horaire UTC le serveur de base de données convertit timestamp with time zone tapez normal timestamp without time zone la valeur renvoyée n'a donc pas d'informations sur le fuseau horaire. Pour rajouter des informations de fuseau horaire, vous pouvez par exemple ajouter +02 à la fin de l'horodatage renvoyé comme ceci :

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

Qui renvoie 2010-01-01 00:00:00+00 au pilote qui peut également être lu correctement par le pilote pg.

Cela fera effectivement la même chose qu'en définissant simplement SET TIME ZONE 'UTC'; dans le serveur de base de données lorsque la connexion est créée et renvoie simplement la colonne timestamptz directement :

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

Qui renverra 2009-12-31 22:00:00+00 .