Costa Rica timezone (GMT-6) handling with UTC storage
CRITICAL STANDARD: ALL dates in this project are handled in Costa Rica local time (UTC-6). Never use toISOString().split('T')[0] directly on UTC dates without converting to Costa Rica timezone first.
The Banca Management Backend operates in Costa Rica timezone (GMT-6) and follows a strict timezone handling standard.
The project includes timezone utilities for consistent date handling:
import { toCostaRicaDate, toCostaRicaDateString, getCostaRicaNow, parseCostaRicaDate} from '../utils/timezone';// Get current date/time in Costa Ricaconst now = getCostaRicaNow(); // Date object in CR timezone// Convert UTC date to Costa Rica date stringconst utcDate = new Date('2025-03-03T18:55:00.000Z'); // 6:55 PM UTCconst crDate = toCostaRicaDate(utcDate); // 2025-03-03 12:55 PM CR// Get date-only string in Costa Rica timezoneconst dateString = toCostaRicaDateString(utcDate); // "2025-03-03"// Parse a date string as Costa Rica timezoneconst parsed = parseCostaRicaDate('2025-03-03'); // Date object at midnight CR time
// From loteriaRules.tsfunction convertCostaRicaTimeToUTC(timeString: string, baseDate: Date): Date { const [hours, minutes] = timeString.split(':').map(Number); // Create date in Costa Rica timezone const crDate = new Date(baseDate); crDate.setHours(hours, minutes, 0, 0); // Offset to UTC (CR is GMT-6, so add 6 hours) const utcDate = new Date(crDate.getTime() + (6 * 60 * 60 * 1000)); return utcDate;}// Example:// Input: "12:55" (12:55 PM Costa Rica time)// Output: Date object at 18:55 UTC (6:55 PM UTC)
Sales cutoff is calculated using Costa Rica timezone:
// Close sales 5 minutes before drawconst sorteoTime = new Date(sorteo.scheduledAt); // UTCconst cutoffMinutes = 5;// Convert to Costa Rica time for calculationconst crSorteoTime = toCostaRicaDate(sorteoTime);const crCutoffTime = new Date(crSorteoTime.getTime() - (cutoffMinutes * 60 * 1000));// Check if current CR time is past cutoffconst now = getCostaRicaNow();if (now > crCutoffTime) { throw new AppError('Sales closed for this sorteo', 400);}
// Scenario: It's 11:00 PM on March 3 in Costa Rica (5:00 AM UTC March 4)const now = new Date(); // 2025-03-04T05:00:00.000Z (UTC)// ❌ WRONG: Returns "2025-03-04" (tomorrow in UTC, but still today in CR!)const wrong = now.toISOString().split('T')[0];// ✅ CORRECT: Returns "2025-03-03" (correct CR date)const correct = toCostaRicaDateString(now);
// User selects "2025-03-03 12:55 PM" in UI// Convert to UTC before sending to APIimport { zonedTimeToUtc } from 'date-fns-tz';const crDate = new Date('2025-03-03 12:55:00');const utcDate = zonedTimeToUtc(crDate, 'America/Costa_Rica');const isoString = utcDate.toISOString(); // "2025-03-03T18:55:00.000Z"// Send to APIfetch('/api/v1/sorteos', { method: 'POST', body: JSON.stringify({ scheduledAt: isoString })});