Files
noteflow/scripts/migrate-calendar-timezone.js
T
Claude 70bc3e0a5a Fix: Décalage horaire Google Calendar (+1h corrigé)
Correction du décalage de timezone de 1h dans Google Calendar

PROBLÈME:
- Les événements s'affichaient avec 1h de décalage
- Événement à 10h → affiché à 11h (ou 09h selon cas)

CAUSE:
- TIMESTAMP (sans timezone) dans PostgreSQL
- Google envoie dates avec timezone info
- PostgreSQL stockait sans timezone
- JavaScript réinterprétait avec timezone local
- = Double application du décalage

SOLUTION:
1. calendar_events: TIMESTAMP → TIMESTAMPTZ
   - start_time: TIMESTAMPTZ (conserve timezone)
   - end_time: TIMESTAMPTZ (conserve timezone)

2. Migration automatique:
   - scripts/migrate-calendar-timezone.js
   - Exécuté automatiquement au démarrage Docker
   - Convertit les données existantes
   - USING start_time AT TIME ZONE 'UTC'

3. Correction booléens all_day:
   - Ligne 433: isAllDay ? 1 : 0 → isAllDay
   - Ligne 451: isAllDay ? 1 : 0 → isAllDay

FICHIERS MODIFIÉS:
- config/database.js: TIMESTAMPTZ pour calendar_events
- routes/calendar.routes.js: Booléens corrigés
- docker-entrypoint.sh: Migration auto timezone
- migrations/002_calendar_timestamptz.sql: SQL manuel
- scripts/migrate-calendar-timezone.js: Script migration

DÉPLOIEMENT:
Au prochain rebuild Docker:
1. La table sera recréée avec TIMESTAMPTZ
2. Les événements existants seront migrés
3. Les nouvelles synchros utiliseront le bon format
4. Plus de décalage horaire!

Resynchronisez Google Calendar après déploiement
pour appliquer le nouveau format.
2025-11-14 10:52:41 +00:00

98 lines
2.7 KiB
JavaScript
Executable File

#!/usr/bin/env node
// Migration: Convertir calendar_events TIMESTAMP → TIMESTAMPTZ
const { Pool } = require('pg');
const DATABASE_URL = process.env.DATABASE_URL;
if (!DATABASE_URL) {
console.error('❌ DATABASE_URL non définie');
process.exit(1);
}
async function migrate() {
const pool = new Pool({ connectionString: DATABASE_URL });
try {
console.log('\n🔄 Migration: calendar_events TIMESTAMP → TIMESTAMPTZ\n');
const client = await pool.connect();
// Vérifier le type actuel
const check = await client.query(`
SELECT column_name, data_type
FROM information_schema.columns
WHERE table_name = 'calendar_events'
AND column_name IN ('start_time', 'end_time')
`);
console.log('📊 Types actuels:');
check.rows.forEach(row => {
console.log(` ${row.column_name}: ${row.data_type}`);
});
// Si déjà TIMESTAMPTZ, skip
const alreadyMigrated = check.rows.every(row =>
row.data_type.includes('timestamp with time zone') ||
row.data_type === 'timestamptz'
);
if (alreadyMigrated) {
console.log('\n✅ Migration déjà effectuée, rien à faire');
client.release();
await pool.end();
return;
}
console.log('\n🔄 Conversion en cours...');
await client.query('BEGIN');
// Convertir start_time
await client.query(`
ALTER TABLE calendar_events
ALTER COLUMN start_time TYPE TIMESTAMPTZ
USING start_time AT TIME ZONE 'UTC'
`);
console.log(' ✅ start_time → TIMESTAMPTZ');
// Convertir end_time
await client.query(`
ALTER TABLE calendar_events
ALTER COLUMN end_time TYPE TIMESTAMPTZ
USING end_time AT TIME ZONE 'UTC'
`);
console.log(' ✅ end_time → TIMESTAMPTZ');
await client.query('COMMIT');
// Vérifier après migration
const verify = await client.query(`
SELECT column_name, data_type
FROM information_schema.columns
WHERE table_name = 'calendar_events'
AND column_name IN ('start_time', 'end_time')
`);
console.log('\n📊 Types après migration:');
verify.rows.forEach(row => {
console.log(` ${row.column_name}: ${row.data_type}`);
});
console.log('\n✅ Migration terminée avec succès!');
console.log('');
console.log('📝 Note: Resynchronisez vos événements Google Calendar');
console.log(' pour appliquer le nouveau format de timezone.');
console.log('');
client.release();
await pool.end();
} catch (error) {
console.error('\n❌ Erreur lors de la migration:', error.message);
process.exit(1);
}
}
migrate();