mirror of
https://github.com/R0m1k3/noteflow.git
synced 2026-10-11 17:29:37 +02:00
Fix: Timezone Europe/Paris + diagnostic complet calendrier
PROBLÈME PERSISTANT: Le décalage d'1h persiste malgré les fixes.
ANALYSE COMPLÈTE:
Le types.setTypeParser doit être appliqué AVANT le Pool,
ET l'image Docker doit être rebuild (pas juste restart),
ET les anciens événements doivent être supprimés et resynchronisés.
AJOUTS:
1. scripts/full-diagnosis-timezone.js
- Diagnostic complet du problème
- Test du type parser (Date object vs string)
- Test insertion/lecture PostgreSQL
- Vérification événements réels
- Simulation API response
- Recommandations claires selon le résultat
2. FIX-TIMEZONE-FINAL.md
- Procédure COMPLÈTE étape par étape
- REBUILD obligatoire avec --no-cache
- Suppression événements corrompus
- Resynchronisation Google Calendar
- Vérifications multiples
- Dépannage si problème persiste
- Checklist finale
UTILISATION:
1. Diagnostic:
docker exec notes-todo-app node scripts/full-diagnosis-timezone.js
2. Si parser KO (renvoie Date objects):
docker-compose down
docker-compose build --no-cache notes-app
docker-compose up -d
3. Suppression anciens événements:
docker exec noteflow-postgres psql -U noteflow -d noteflow -p 5499 \
-c "DELETE FROM calendar_events"
4. Resynchroniser depuis interface web
5. Vérifier que heures = Google Calendar
Le diagnostic permettra d'identifier si:
- Le parser n'est pas actif → rebuild nécessaire
- Le parser fonctionne mais anciennes données → suppression nécessaire
- Autre problème → affichage exact du problème
Fichiers:
- scripts/full-diagnosis-timezone.js (nouveau)
- FIX-TIMEZONE-FINAL.md (guide complet)
This commit is contained in:
2 files changed
+444
No files matched your search
Executable
+171
@@ -0,0 +1,171 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
// DIAGNOSTIC COMPLET - Traçage du décalage horaire
|
||||
const { Pool } = require('pg');
|
||||
|
||||
const DATABASE_URL = process.env.DATABASE_URL;
|
||||
|
||||
async function fullDiagnosis() {
|
||||
const pool = new Pool({ connectionString: DATABASE_URL });
|
||||
|
||||
try {
|
||||
console.log('\n╔══════════════════════════════════════════════════════════════╗');
|
||||
console.log('║ DIAGNOSTIC COMPLET - DÉCALAGE HORAIRE CALENDRIER ║');
|
||||
console.log('╚══════════════════════════════════════════════════════════════╝\n');
|
||||
|
||||
const client = await pool.connect();
|
||||
|
||||
// 1. Vérifier la configuration du driver pg
|
||||
console.log('1️⃣ CONFIGURATION DRIVER PG:\n');
|
||||
const types = require('pg').types;
|
||||
const parser1184 = types.getTypeParser(1184);
|
||||
console.log(` Type parser 1184 (TIMESTAMPTZ): ${typeof parser1184}`);
|
||||
console.log(` Parser renvoie: ${parser1184.name || 'function'}\n`);
|
||||
|
||||
// 2. Test direct avec une date connue
|
||||
console.log('2️⃣ TEST INSERTION/LECTURE DIRECTE:\n');
|
||||
|
||||
await client.query('DELETE FROM calendar_events WHERE google_event_id LIKE $1', ['diagnostic-%']);
|
||||
|
||||
const testDates = [
|
||||
{ name: 'Paris 10h avec offset', value: '2025-11-14T10:00:00+01:00' },
|
||||
{ name: 'UTC 09h', value: '2025-11-14T09:00:00Z' },
|
||||
{ name: 'Paris 14h avec offset', value: '2025-11-14T14:30:00+01:00' }
|
||||
];
|
||||
|
||||
for (const test of testDates) {
|
||||
const eventId = `diagnostic-${test.name.replace(/\s+/g, '-')}`;
|
||||
|
||||
await client.query(`
|
||||
INSERT INTO calendar_events
|
||||
(google_event_id, user_id, title, start_time, end_time, all_day)
|
||||
VALUES ($1, 1, $2, $3, $4, FALSE)
|
||||
`, [eventId, `Test ${test.name}`, test.value, test.value]);
|
||||
|
||||
const result = await client.query(`
|
||||
SELECT
|
||||
title,
|
||||
start_time,
|
||||
pg_typeof(start_time) as pg_type,
|
||||
start_time::text as text_repr
|
||||
FROM calendar_events
|
||||
WHERE google_event_id = $1
|
||||
`, [eventId]);
|
||||
|
||||
const row = result.rows[0];
|
||||
console.log(` Test: ${test.name}`);
|
||||
console.log(` Inséré: ${test.value}`);
|
||||
console.log(` Type PG: ${row.pg_type}`);
|
||||
console.log(` Texte: ${row.text_repr}`);
|
||||
console.log(` JS type: ${typeof row.start_time}`);
|
||||
console.log(` JS value: ${row.start_time}`);
|
||||
|
||||
if (typeof row.start_time === 'object' && row.start_time instanceof Date) {
|
||||
console.log(` ❌ PROBLÈME: C'est un objet Date! Le parser n'a pas fonctionné!`);
|
||||
console.log(` toISOString(): ${row.start_time.toISOString()}`);
|
||||
} else if (typeof row.start_time === 'string') {
|
||||
console.log(` ✅ OK: C'est une string!`);
|
||||
const parsed = new Date(row.start_time);
|
||||
console.log(` new Date(): ${parsed.toISOString()}`);
|
||||
console.log(` Heure locale: ${parsed.toLocaleTimeString('fr-FR', { hour: '2-digit', minute: '2-digit' })}`);
|
||||
console.log(` Heure Paris: ${parsed.toLocaleTimeString('fr-FR', { hour: '2-digit', minute: '2-digit', timeZone: 'Europe/Paris' })}`);
|
||||
}
|
||||
console.log('');
|
||||
}
|
||||
|
||||
// 3. Vérifier événements réels
|
||||
console.log('3️⃣ ÉVÉNEMENTS RÉELS GOOGLE CALENDAR:\n');
|
||||
|
||||
const realEvents = await client.query(`
|
||||
SELECT
|
||||
title,
|
||||
start_time,
|
||||
pg_typeof(start_time) as pg_type,
|
||||
start_time::text as text_repr,
|
||||
all_day
|
||||
FROM calendar_events
|
||||
WHERE google_event_id NOT LIKE 'diagnostic-%'
|
||||
ORDER BY start_time ASC
|
||||
LIMIT 3
|
||||
`);
|
||||
|
||||
if (realEvents.rows.length === 0) {
|
||||
console.log(' ⚠️ Aucun événement réel trouvé');
|
||||
console.log(' → Synchronisez Google Calendar d\'abord\n');
|
||||
} else {
|
||||
realEvents.rows.forEach((evt, i) => {
|
||||
console.log(` Événement ${i + 1}: ${evt.title}`);
|
||||
console.log(` Type PG: ${evt.pg_type}`);
|
||||
console.log(` Texte: ${evt.text_repr}`);
|
||||
console.log(` JS type: ${typeof evt.start_time}`);
|
||||
console.log(` JS value: ${evt.start_time}`);
|
||||
|
||||
if (typeof evt.start_time === 'object' && evt.start_time instanceof Date) {
|
||||
console.log(` ❌ Objet Date (parser KO)`);
|
||||
console.log(` Affiché frontend: ${evt.start_time.toLocaleTimeString('fr-FR', { hour: '2-digit', minute: '2-digit', timeZone: 'Europe/Paris' })}`);
|
||||
} else {
|
||||
console.log(` ✅ String (parser OK)`);
|
||||
const d = new Date(evt.start_time);
|
||||
console.log(` Affiché frontend: ${d.toLocaleTimeString('fr-FR', { hour: '2-digit', minute: '2-digit', timeZone: 'Europe/Paris' })}`);
|
||||
}
|
||||
console.log('');
|
||||
});
|
||||
}
|
||||
|
||||
// 4. Test de l'API
|
||||
console.log('4️⃣ SIMULATION API RESPONSE:\n');
|
||||
|
||||
const apiResult = await client.query(`
|
||||
SELECT
|
||||
id, google_event_id, title, description,
|
||||
start_time, end_time, location, html_link, all_day
|
||||
FROM calendar_events
|
||||
WHERE google_event_id LIKE 'diagnostic-%'
|
||||
LIMIT 1
|
||||
`);
|
||||
|
||||
if (apiResult.rows.length > 0) {
|
||||
const apiEvent = apiResult.rows[0];
|
||||
console.log(' API renvoie (format JSON):');
|
||||
console.log(JSON.stringify(apiEvent, null, 2));
|
||||
console.log('');
|
||||
}
|
||||
|
||||
// 5. Recommandations
|
||||
console.log('╔══════════════════════════════════════════════════════════════╗');
|
||||
console.log('║ DIAGNOSTIC RÉSULTAT ║');
|
||||
console.log('╚══════════════════════════════════════════════════════════════╝\n');
|
||||
|
||||
const sampleEvent = realEvents.rows[0] || testDates[0];
|
||||
const isDateObject = typeof sampleEvent?.start_time === 'object';
|
||||
|
||||
if (isDateObject) {
|
||||
console.log('❌ PROBLÈME TROUVÉ:\n');
|
||||
console.log(' Le driver pg renvoie toujours des objets Date');
|
||||
console.log(' Le types.setTypeParser(1184) n\'a PAS été appliqué\n');
|
||||
console.log('💡 SOLUTION:\n');
|
||||
console.log(' 1. Vérifier que config/database.js a bien:');
|
||||
console.log(' const { Pool, types } = require(\'pg\');');
|
||||
console.log(' types.setTypeParser(1184, ...) AVANT le Pool\n');
|
||||
console.log(' 2. Rebuild: docker-compose build notes-app\n');
|
||||
console.log(' 3. Restart: docker-compose restart notes-app\n');
|
||||
} else {
|
||||
console.log('✅ Le parser fonctionne!\n');
|
||||
console.log(' Les dates sont renvoyées comme strings');
|
||||
console.log(' Le problème doit être ailleurs (frontend?)\n');
|
||||
}
|
||||
|
||||
// Cleanup
|
||||
await client.query('DELETE FROM calendar_events WHERE google_event_id LIKE $1', ['diagnostic-%']);
|
||||
|
||||
client.release();
|
||||
await pool.end();
|
||||
|
||||
} catch (error) {
|
||||
console.error('\n❌ Erreur:', error.message);
|
||||
console.error(error.stack);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
fullDiagnosis();
|
||||
Reference in new issue
Block a user