/** * One-off data migration: fix group-stage match times stored as local-wall-time-as-UTC. * * Before the schedule-form fix, the admin's local wall-clock time (PDT, UTC-7) was * stored as if it were UTC, so every `group_stage_matches.scheduled_at` is 7 hours * behind the true UTC instant. This shifts them +7 hours. * * Scope: ONLY `group_stage_matches.scheduled_at` (where not null). Playoff games * (`playoff_match_games.scheduled_at`) were saved correctly and are left untouched. * * NOT idempotent — running with --apply twice double-shifts. Defaults to a dry-run; * pass --apply to write. * * Usage (loads .env via dotenv-cli): * npx dotenv -- node scripts/fix-group-match-times-utc.mjs # preview * npx dotenv -- node scripts/fix-group-match-times-utc.mjs --apply # apply */ import postgres from "postgres"; const SHIFT = "7 hours"; // PDT (UTC-7) wall-clock stored as UTC -> true UTC const apply = process.argv.includes("--apply"); const DATABASE_URL = process.env.DATABASE_DIRECT_URL || process.env.DATABASE_URL; if (!DATABASE_URL) { console.error("ERROR: DATABASE_DIRECT_URL (or DATABASE_URL) is required"); process.exit(1); } const sql = postgres(DATABASE_URL, { max: 1, onnotice: () => {} }); try { const [{ count }] = await sql` SELECT COUNT(*)::int AS count FROM group_stage_matches WHERE scheduled_at IS NOT NULL `; console.log(`Group-stage matches with a scheduled time: ${count}`); if (count === 0) { console.log("Nothing to do."); await sql.end(); process.exit(0); } const samples = await sql` SELECT id, scheduled_at AS before, scheduled_at + ${sql.unsafe(`interval '${SHIFT}'`)} AS after FROM group_stage_matches WHERE scheduled_at IS NOT NULL ORDER BY scheduled_at LIMIT 10 `; console.log(`\nSample before -> after (+${SHIFT}):`); for (const r of samples) { console.log(` ${r.id}: ${r.before.toISOString()} -> ${r.after.toISOString()}`); } if (!apply) { console.log(`\nDRY RUN — no changes written. Re-run with --apply to shift ${count} row(s) +${SHIFT}.`); await sql.end(); process.exit(0); } const result = await sql` UPDATE group_stage_matches SET scheduled_at = scheduled_at + ${sql.unsafe(`interval '${SHIFT}'`)} WHERE scheduled_at IS NOT NULL `; console.log(`\nApplied: shifted ${result.count} row(s) +${SHIFT}.`); await sql.end(); process.exit(0); } catch (err) { console.error("Migration failed:", err); await sql.end().catch(() => {}); process.exit(1); }