# Timezone Handling Analysis

## Current Situation

### ✅ What's Working Correctly

**Database Storage**:
- PostgreSQL stores timestamps as `timestamptz` (timestamp with timezone)
- All race start times are stored in **UTC**
- Example: `2026-01-13 04:49:00+00` (UTC)
- This is the **correct** approach - always store in UTC

**API to Database**:
- TAB API returns timestamps (likely in UTC or with timezone info)
- Code uses: `new Date(race.start_time)` at line 227 of `meeting-service.ts`
- JavaScript Date automatically handles timezone conversion
- Stored correctly in PostgreSQL as UTC

### ⚠️ Timezone Configuration Issues

**Problem #1: Scheduler Timezone is Australia/Sydney**

All schedulers are configured with:
```typescript
timezone: 'Australia/Sydney'
```

But you're operating in **New Zealand** (Pacific/Auckland).

**Time Difference**:
- NZ (NZDT): UTC+13 (summer) / UTC+12 (winter)
- Sydney (AEDT): UTC+11 (summer) / UTC+10 (winter)
- **Difference: NZ is 2 hours ahead of Sydney**

**Impact on Schedulers**:

1. **Morning Scrape** (`0 6 * * *` in Sydney time)
   - Currently runs: 6:00 AM Sydney = **8:00 AM NZ**
   - Should probably run: 6:00 AM NZ

2. **Pre-Race Updates** (every 5 minutes)
   - No direct impact since they run continuously
   - BUT the time window calculations use Sydney timezone
   - Could miss or double-update races near timezone boundaries

3. **Post-Race Updates** (every 5 minutes)
   - Same issue - uses Sydney time for calculations
   - May check for results at wrong times

**Problem #2: Time Window Calculations**

In `pre-race-scheduler.ts` line 132:
```typescript
const now = DateTime.now().setZone('Australia/Sydney');
```

This means:
- Scheduler thinks "now" is Sydney time
- But races are stored in UTC
- When comparing, it converts UTC race times to Sydney time
- **This is wrong for NZ races!**

### Example Scenario

**Real NZ Race**:
- Starts: 5:00 PM NZ (2026-01-14 17:00 NZDT)
- Stored in DB: 2026-01-14 04:00:00+00 (UTC)

**What Happens Now** (using Sydney timezone):
- Scheduler runs at: 4:00 PM NZ time
- Scheduler thinks it's: 2:00 PM Sydney time
- Looks for races at: 3:00 PM Sydney (T-60)
- Converts to UTC: 04:00 UTC
- **Finds the race** ✓ (accidentally works)

**But this breaks when**:
- Daylight saving transitions occur
- Sydney and NZ change on different dates
- Suddenly the offset changes from 2 hours to 3 hours
- Races get missed or double-updated

## What Needs to Change

### Option 1: Change Scheduler Timezone to Pacific/Auckland

**Pros**:
- Correct for NZ operation
- Cron schedules run at expected NZ times
- Time windows calculated correctly for NZ

**Cons**:
- If you ever want to support AU races, need separate config

### Option 2: Keep UTC for Everything

**Pros**:
- No timezone ambiguity
- Works globally
- Standard practice

**Cons**:
- Cron expressions in UTC are hard to read
- "6 AM" scrape becomes "17:00 UTC" (confusing)

### Option 3: Timezone Per Country (Best for Multi-Region)

**Pros**:
- Can handle both NZ and AU races correctly
- Each race uses its local timezone

**Cons**:
- More complex implementation
- Need country-to-timezone mapping

## Recommended Fix

**For NZ-only operation**: Use Option 1

Change all timezone references from `Australia/Sydney` to `Pacific/Auckland`:

### Files to Update:

1. **`src/schedulers/config.ts`** (6 locations)
   ```typescript
   timezone: 'Pacific/Auckland'  // was: 'Australia/Sydney'
   ```

2. **`src/schedulers/pre-race-scheduler.ts`** (line 132)
   ```typescript
   const now = DateTime.now().setZone('Pacific/Auckland');
   ```

3. **`src/schedulers/post-race-scheduler.ts`** (line 193)
   ```typescript
   const now = DateTime.now().setZone('Pacific/Auckland');
   ```

4. **`src/schedulers/cleanup-scheduler.ts`** (line 42)
   ```typescript
   .setZone('Pacific/Auckland')
   ```

5. **`src/schedulers/morning-scrape-scheduler.ts`** (line 182)
   ```typescript
   const now = DateTime.now().setZone('Pacific/Auckland');
   ```

6. **`src/schedulers/base-scheduler.ts`** (line 81)
   ```typescript
   timezone: this.config.timezone || 'Pacific/Auckland',
   ```

7. **`src/schedulers/types.ts`** (comment at line 24)
   ```typescript
   // Default: 'Pacific/Auckland'
   ```

## Testing After Changes

1. **Morning Scrape**:
   - Will now run at 6:00 AM NZ time (was 8:00 AM NZ)
   - Verify it runs at the right time

2. **Pre-Race Updates**:
   - Time windows now calculated in NZ time
   - Test with upcoming NZ races
   - Verify T-60 and T-15 trigger correctly

3. **Post-Race Updates**:
   - Results fetched relative to NZ time
   - Verify provisional->confirmed transition works

## Environment Variable Option

For flexibility, you could make timezone configurable:

**.env**:
```env
SCHEDULER_TIMEZONE=Pacific/Auckland
```

**config.ts**:
```typescript
timezone: process.env.SCHEDULER_TIMEZONE || 'Pacific/Auckland'
```

Then easily change if needed for different deployments.

## Verification Queries

After making changes, verify with:

```sql
-- Check current time in different zones
SELECT
  NOW() as utc_now,
  NOW() AT TIME ZONE 'Pacific/Auckland' as nz_now,
  NOW() AT TIME ZONE 'Australia/Sydney' as sydney_now;

-- Check upcoming races
SELECT
  "startTime" as utc_time,
  "startTime" AT TIME ZONE 'Pacific/Auckland' as nz_time,
  name
FROM races
WHERE "startTime" > NOW()
ORDER BY "startTime"
LIMIT 5;
```

## Bottom Line

**Current State**:
- ⚠️ Schedulers use Sydney timezone but you're in NZ
- ⚠️ 2-hour offset means things "mostly work" but are fragile
- ⚠️ Will break during daylight saving transitions

**Recommended Action**:
- ✅ Change all timezone references to `Pacific/Auckland`
- ✅ Test morning scrape runs at correct NZ time
- ✅ Verify pre/post-race schedulers find races correctly

**Impact of Not Fixing**:
- Morning scrape runs 2 hours late (8 AM instead of 6 AM)
- Race updates may be late or early depending on DST
- Confusion when debugging "why didn't it update?"

The database itself is fine (UTC storage is correct). Only the scheduler timezone configuration needs updating.
