diff --git a/config/database.js b/config/database.js index 780f3cf..b145772 100644 --- a/config/database.js +++ b/config/database.js @@ -1,8 +1,16 @@ // Configuration et initialisation de la base de données PostgreSQL -const { Pool } = require('pg'); +const { Pool, types } = require('pg'); const bcrypt = require('bcrypt'); const logger = require('./logger'); +// IMPORTANT: Désactiver le parsing automatique des TIMESTAMPTZ en objets Date +// Pour éviter les problèmes de timezone, on renvoie les dates comme strings ISO +types.setTypeParser(1184, function(stringValue) { + // 1184 = TIMESTAMPTZ + // Renvoyer la string ISO au lieu d'un objet Date + return stringValue; +}); + // Configuration PostgreSQL depuis DATABASE_URL ou variables d'environnement const DATABASE_URL = process.env.DATABASE_URL || `postgresql://${process.env.PGUSER || 'noteflow'}:${process.env.PGPASSWORD || 'noteflow_secure_password_change_me'}@${process.env.PGHOST || 'localhost'}:${process.env.PGPORT || '5499'}/${process.env.PGDATABASE || 'noteflow'}`; diff --git a/scripts/test-date-format.js b/scripts/test-date-format.js new file mode 100755 index 0000000..4ae7b53 --- /dev/null +++ b/scripts/test-date-format.js @@ -0,0 +1,144 @@ +#!/usr/bin/env node + +// Test du format de date renvoyé par PostgreSQL +const { Pool } = require('pg'); + +const DATABASE_URL = process.env.DATABASE_URL; + +async function testDateFormat() { + const pool = new Pool({ connectionString: DATABASE_URL }); + + try { + console.log('\n╔════════════════════════════════════════════════════════════╗'); + console.log('║ TEST FORMAT DATES POSTGRESQL → JAVASCRIPT ║'); + console.log('╚════════════════════════════════════════════════════════════╝\n'); + + const client = await pool.connect(); + + // Insérer un événement de test + console.log('1️⃣ Insertion d\'un événement de test...\n'); + + await client.query('DELETE FROM calendar_events'); + + const testDate = '2025-11-14T10:00:00+01:00'; // 10h Paris + await client.query(` + INSERT INTO calendar_events + (google_event_id, user_id, title, description, start_time, end_time, all_day) + VALUES + ($1, 1, $2, $3, $4, $5, FALSE) + `, [ + 'test-event-123', + 'Test Événement 10h Paris', + 'Test timezone', + testDate, + testDate + ]); + + console.log(` Test inséré: ${testDate}`); + console.log(' (10h heure de Paris avec offset +01:00)\n'); + + // Récupérer l'événement + console.log('2️⃣ Récupération depuis PostgreSQL...\n'); + + const result = await client.query(` + SELECT + title, + start_time, + pg_typeof(start_time) as pg_type, + to_char(start_time, 'YYYY-MM-DD HH24:MI:SS TZ') as formatted_pg, + start_time::text as text_representation + FROM calendar_events + WHERE google_event_id = 'test-event-123' + `); + + const event = result.rows[0]; + console.log(' Côté PostgreSQL:'); + console.log(` Type: ${event.pg_type}`); + console.log(` Formaté: ${event.formatted_pg}`); + console.log(` Texte: ${event.text_representation}`); + + console.log('\n Côté JavaScript (driver pg):'); + console.log(` typeof start_time: ${typeof event.start_time}`); + console.log(` start_time instanceof Date: ${event.start_time instanceof Date}`); + console.log(` start_time value: ${event.start_time}`); + + if (event.start_time instanceof Date) { + console.log(` start_time.toISOString(): ${event.start_time.toISOString()}`); + console.log(` start_time.getTime(): ${event.start_time.getTime()}`); + console.log(` start_time.toString(): ${event.start_time.toString()}`); + console.log(` start_time.toLocaleString('fr-FR'): ${event.start_time.toLocaleString('fr-FR')}`); + console.log(` start_time.toLocaleString('fr-FR', {timeZone: 'Europe/Paris'}): ${event.start_time.toLocaleString('fr-FR', { timeZone: 'Europe/Paris' })}`); + console.log(` start_time.toLocaleTimeString('fr-FR', {hour: '2-digit', minute: '2-digit'}): ${event.start_time.toLocaleTimeString('fr-FR', { hour: '2-digit', minute: '2-digit' })}`); + console.log(` start_time.toLocaleTimeString('fr-FR', {hour: '2-digit', minute: '2-digit', timeZone: 'Europe/Paris'}): ${event.start_time.toLocaleTimeString('fr-FR', { hour: '2-digit', minute: '2-digit', timeZone: 'Europe/Paris' })}`); + } + + // Tester avec SELECT sans conversion + console.log('\n3️⃣ Test SELECT raw...\n'); + + const rawResult = await client.query(` + SELECT start_time FROM calendar_events WHERE google_event_id = 'test-event-123' + `); + + const rawDate = rawResult.rows[0].start_time; + console.log(` Raw date from SELECT: ${rawDate}`); + console.log(` Type: ${typeof rawDate}`); + + if (rawDate instanceof Date) { + const hours = rawDate.getHours(); + const minutes = rawDate.getMinutes(); + console.log(` getHours(): ${hours}`); + console.log(` getMinutes(): ${minutes}`); + console.log(` UTC hours: ${rawDate.getUTCHours()}`); + console.log(` UTC minutes: ${rawDate.getUTCMinutes()}`); + } + + // Comparer avec la façon dont c'était fait avec SQLite + console.log('\n4️⃣ Simulation SQLite (string)...\n'); + + const sqliteLikeDate = new Date('2025-11-14T10:00:00+01:00'); + console.log(` new Date('2025-11-14T10:00:00+01:00'):`); + console.log(` toLocaleTimeString: ${sqliteLikeDate.toLocaleTimeString('fr-FR', { hour: '2-digit', minute: '2-digit' })}`); + console.log(` getHours(): ${sqliteLikeDate.getHours()}`); + + // Test avec string UTC + const utcString = '2025-11-14T09:00:00.000Z'; + const dateFromUtc = new Date(utcString); + console.log(`\n new Date('${utcString}'):`); + console.log(` toLocaleTimeString: ${dateFromUtc.toLocaleTimeString('fr-FR', { hour: '2-digit', minute: '2-digit' })}`); + console.log(` toLocaleTimeString (Europe/Paris): ${dateFromUtc.toLocaleTimeString('fr-FR', { hour: '2-digit', minute: '2-digit', timeZone: 'Europe/Paris' })}`); + console.log(` getHours(): ${dateFromUtc.getHours()}`); + + console.log('\n╔════════════════════════════════════════════════════════════╗'); + console.log('║ DIAGNOSTIC COMPLET ║'); + console.log('╚════════════════════════════════════════════════════════════╝\n'); + + console.log('📊 RÉSUMÉ:\n'); + + if (event.start_time instanceof Date) { + const pgHour = event.start_time.toLocaleTimeString('fr-FR', { hour: '2-digit', minute: '2-digit', timeZone: 'Europe/Paris' }); + const expectedHour = '10:00'; + + if (pgHour === expectedHour) { + console.log(` ✅ PostgreSQL renvoie la BONNE heure: ${pgHour}`); + console.log(' → Le problème est ailleurs (cache frontend?)\n'); + } else { + console.log(` ❌ PostgreSQL renvoie une MAUVAISE heure: ${pgHour}`); + console.log(` → Attendu: ${expectedHour}`); + console.log(` → Problème dans le stockage PostgreSQL\n`); + } + } + + // Cleanup + await client.query('DELETE FROM calendar_events WHERE google_event_id = $1', ['test-event-123']); + + client.release(); + await pool.end(); + + } catch (error) { + console.error('\n❌ Erreur:', error.message); + console.error(error.stack); + process.exit(1); + } +} + +testDateFormat();