Files
noteflow/scripts/check-calendar-timezone.js
Claude f3f64a5a0d Fix: Timezone Europe/Paris + diagnostic complet calendrier
Problème: Décalage d'1 heure persistant malgré types.setTypeParser
Cause probable: Container pas rebuild avec le fix database.js

Ajouts:
1. scripts/check-calendar-timezone.js
   - Diagnostic complet timezone PostgreSQL/Node.js
   - Vérifie si types.setTypeParser(1184) fonctionne
   - Affiche type de données retourné (string vs Date object)
   - Compare valeurs SQL brutes avec valeurs JS

2. CALENDAR_TIMEZONE_FIX.md
   - Documentation complète du problème
   - Procédure de fix étape par étape
   - Explication technique de la cause
   - Historique des tentatives

Utilisation:
```bash
# 1. Diagnostic
node scripts/check-calendar-timezone.js

# 2. Si Date object au lieu de string:
docker-compose build --no-cache notes-app
docker-compose up -d

# 3. Resynchroniser calendrier depuis UI
```

Le fix types.setTypeParser(1184) est déjà en place dans database.js
mais nécessite un rebuild du container pour être actif.
2025-11-15 07:08:20 +00:00

112 lines
4.2 KiB
JavaScript
Executable File

#!/usr/bin/env node
/**
* Script de diagnostic pour vérifier le parsing des TIMESTAMPTZ
* et le décalage horaire dans le calendrier
*/
const { getAll, getOne } = require('../config/database');
const logger = require('../config/logger');
async function checkTimezone() {
try {
console.log('\n=== DIAGNOSTIC TIMEZONE CALENDRIER ===\n');
// 1. Vérifier la timezone de PostgreSQL
const pgTimezone = await getOne('SHOW timezone');
console.log('1. Timezone PostgreSQL:', pgTimezone.timezone);
// 2. Vérifier la timezone système Node.js
const nodeTimezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
console.log('2. Timezone Node.js:', nodeTimezone);
console.log('3. TZ env var:', process.env.TZ || 'non défini');
// 3. Récupérer un événement de test
const event = await getOne(`
SELECT
id,
title,
start_time,
end_time,
all_day,
pg_typeof(start_time) as type_start
FROM calendar_events
ORDER BY start_time DESC
LIMIT 1
`);
if (!event) {
console.log('\n❌ Aucun événement trouvé dans la base de données');
console.log(' Veuillez synchroniser avec Google Calendar d\'abord\n');
return;
}
console.log('\n4. Événement récupéré:');
console.log(' - ID:', event.id);
console.log(' - Titre:', event.title);
console.log(' - Type SQL de start_time:', event.type_start);
console.log(' - start_time (brut):', event.start_time);
console.log(' - Type JS de start_time:', typeof event.start_time);
console.log(' - end_time (brut):', event.end_time);
console.log(' - Type JS de end_time:', typeof event.end_time);
console.log(' - all_day:', event.all_day);
// 4. Tester la conversion en Date
if (typeof event.start_time === 'string') {
const dateObj = new Date(event.start_time);
console.log('\n5. Conversion en Date object:');
console.log(' - new Date(start_time):', dateObj);
console.log(' - toISOString():', dateObj.toISOString());
console.log(' - toLocaleString("fr-FR"):', dateObj.toLocaleString('fr-FR'));
console.log(' - toLocaleString("fr-FR", {timeZone: "Europe/Paris"}):',
dateObj.toLocaleString('fr-FR', { timeZone: 'Europe/Paris' }));
console.log(' - Offset timezone (minutes):', dateObj.getTimezoneOffset());
} else {
console.log('\n⚠️ WARNING: start_time n\'est PAS une string!');
console.log(' Le types.setTypeParser(1184) ne fonctionne pas correctement');
console.log(' Le container doit être rebuild avec --no-cache');
}
// 5. Récupérer la valeur brute SQL
const rawEvent = await getOne(`
SELECT
start_time::text as start_text,
start_time AT TIME ZONE 'UTC' as start_utc,
start_time AT TIME ZONE 'Europe/Paris' as start_paris
FROM calendar_events
WHERE id = $1
`, [event.id]);
console.log('\n6. Valeurs SQL brutes:');
console.log(' - start_time::text:', rawEvent.start_text);
console.log(' - start_time AT TIME ZONE \'UTC\':', rawEvent.start_utc);
console.log(' - start_time AT TIME ZONE \'Europe/Paris\':', rawEvent.start_paris);
// 6. Compter les événements
const count = await getOne('SELECT COUNT(*) as count FROM calendar_events');
console.log('\n7. Nombre total d\'événements:', count.count);
console.log('\n=== FIN DIAGNOSTIC ===\n');
// Recommandations
if (typeof event.start_time !== 'string') {
console.log('⚠️ ACTION REQUISE:');
console.log(' 1. Rebuild le container avec --no-cache:');
console.log(' docker-compose build --no-cache notes-app');
console.log(' 2. Restart le container:');
console.log(' docker-compose restart notes-app');
console.log(' 3. Resynchroniser le calendrier depuis l\'interface web\n');
} else {
console.log('✓ types.setTypeParser fonctionne correctement');
console.log(' Les dates sont retournées comme strings\n');
}
process.exit(0);
} catch (error) {
console.error('\n❌ Erreur:', error);
process.exit(1);
}
}
checkTimezone();