diff --git a/SportsTimeTests/ScenarioAPlannerSwiftTests.swift b/SportsTimeTests/ScenarioAPlannerSwiftTests.swift index 842ae05..959aa5b 100644 --- a/SportsTimeTests/ScenarioAPlannerSwiftTests.swift +++ b/SportsTimeTests/ScenarioAPlannerSwiftTests.swift @@ -669,4 +669,202 @@ struct ScenarioAPlannerSwiftTests { #expect(option.isValid) } } + + // MARK: - Timezone Boundary Tests + + @Test("game at range start in different timezone is included") + func plan_GameAtRangeStartDifferentTimezone_Included() { + // Date range: Jan 5 00:00 PST to Jan 10 23:59 PST + let pstCalendar = Calendar.current + var pstComponents = DateComponents() + pstComponents.year = 2026 + pstComponents.month = 1 + pstComponents.day = 5 + pstComponents.hour = 0 + pstComponents.minute = 0 + pstComponents.timeZone = TimeZone(identifier: "America/Los_Angeles")! + let rangeStart = pstCalendar.date(from: pstComponents)! + + var endComponents = DateComponents() + endComponents.year = 2026 + endComponents.month = 1 + endComponents.day = 10 + endComponents.hour = 23 + endComponents.minute = 59 + endComponents.timeZone = TimeZone(identifier: "America/Los_Angeles")! + let rangeEnd = pstCalendar.date(from: endComponents)! + + let dateRange = DateInterval(start: rangeStart, end: rangeEnd) + + // Game: Jan 5 19:00 EST (New York) = Jan 5 16:00 PST + let nyStadium = makeStadium(city: "New York", latitude: 40.7128, longitude: -74.0060) + + var estComponents = DateComponents() + estComponents.year = 2026 + estComponents.month = 1 + estComponents.day = 5 + estComponents.hour = 19 + estComponents.minute = 0 + estComponents.timeZone = TimeZone(identifier: "America/New_York")! + let gameTime = pstCalendar.date(from: estComponents)! + + let game = makeGame(stadiumId: nyStadium.id, dateTime: gameTime) + + let result = plan( + games: [game], + stadiums: [nyStadium], + dateRange: dateRange + ) + + // Game should be included (within PST range) + #expect(result.isSuccess) + #expect(result.options.first?.stops.count == 1) + } + + @Test("game just before range start in different timezone is excluded") + func plan_GameBeforeRangeStartDifferentTimezone_Excluded() { + // Date range: Jan 5 00:00 PST to Jan 10 23:59 PST + let pstCalendar = Calendar.current + var pstComponents = DateComponents() + pstComponents.year = 2026 + pstComponents.month = 1 + pstComponents.day = 5 + pstComponents.hour = 0 + pstComponents.minute = 0 + pstComponents.timeZone = TimeZone(identifier: "America/Los_Angeles")! + let rangeStart = pstCalendar.date(from: pstComponents)! + + var endComponents = DateComponents() + endComponents.year = 2026 + endComponents.month = 1 + endComponents.day = 10 + endComponents.hour = 23 + endComponents.minute = 59 + endComponents.timeZone = TimeZone(identifier: "America/Los_Angeles")! + let rangeEnd = pstCalendar.date(from: endComponents)! + + let dateRange = DateInterval(start: rangeStart, end: rangeEnd) + + // Game: Jan 4 22:00 EST (New York) = Jan 4 19:00 PST + let nyStadium = makeStadium(city: "New York", latitude: 40.7128, longitude: -74.0060) + + var estComponents = DateComponents() + estComponents.year = 2026 + estComponents.month = 1 + estComponents.day = 4 + estComponents.hour = 22 + estComponents.minute = 0 + estComponents.timeZone = TimeZone(identifier: "America/New_York")! + let gameTime = pstCalendar.date(from: estComponents)! + + let game = makeGame(stadiumId: nyStadium.id, dateTime: gameTime) + + let result = plan( + games: [game], + stadiums: [nyStadium], + dateRange: dateRange + ) + + // Game should be excluded (before PST range start) + #expect(result.failure?.reason == .noGamesInRange) + } + + @Test("game at range end in different timezone is included") + func plan_GameAtRangeEndDifferentTimezone_Included() { + // Date range: Jan 5 00:00 PST to Jan 10 23:59 PST + let pstCalendar = Calendar.current + var pstComponents = DateComponents() + pstComponents.year = 2026 + pstComponents.month = 1 + pstComponents.day = 5 + pstComponents.hour = 0 + pstComponents.minute = 0 + pstComponents.timeZone = TimeZone(identifier: "America/Los_Angeles")! + let rangeStart = pstCalendar.date(from: pstComponents)! + + var endComponents = DateComponents() + endComponents.year = 2026 + endComponents.month = 1 + endComponents.day = 10 + endComponents.hour = 23 + endComponents.minute = 59 + endComponents.timeZone = TimeZone(identifier: "America/Los_Angeles")! + let rangeEnd = pstCalendar.date(from: endComponents)! + + let dateRange = DateInterval(start: rangeStart, end: rangeEnd) + + // Game: Jan 10 21:00 EST (New York) = Jan 10 18:00 PST + let nyStadium = makeStadium(city: "New York", latitude: 40.7128, longitude: -74.0060) + + var estComponents = DateComponents() + estComponents.year = 2026 + estComponents.month = 1 + estComponents.day = 10 + estComponents.hour = 21 + estComponents.minute = 0 + estComponents.timeZone = TimeZone(identifier: "America/New_York")! + let gameTime = pstCalendar.date(from: estComponents)! + + let game = makeGame(stadiumId: nyStadium.id, dateTime: gameTime) + + let result = plan( + games: [game], + stadiums: [nyStadium], + dateRange: dateRange + ) + + // Game should be included (within PST range) + #expect(result.isSuccess) + #expect(result.options.first?.stops.count == 1) + } + + @Test("game just after range end in different timezone is excluded") + func plan_GameAfterRangeEndDifferentTimezone_Excluded() { + // Date range: Jan 5 00:00 PST to Jan 10 23:59 PST + let pstCalendar = Calendar.current + var pstComponents = DateComponents() + pstComponents.year = 2026 + pstComponents.month = 1 + pstComponents.day = 5 + pstComponents.hour = 0 + pstComponents.minute = 0 + pstComponents.timeZone = TimeZone(identifier: "America/Los_Angeles")! + let rangeStart = pstCalendar.date(from: pstComponents)! + + var endComponents = DateComponents() + endComponents.year = 2026 + endComponents.month = 1 + endComponents.day = 10 + endComponents.hour = 23 + endComponents.minute = 59 + endComponents.timeZone = TimeZone(identifier: "America/Los_Angeles")! + let rangeEnd = pstCalendar.date(from: endComponents)! + + let dateRange = DateInterval(start: rangeStart, end: rangeEnd) + + // Game: Jan 11 02:00 EST (New York) = Jan 10 23:00 PST + // This is actually WITHIN the range (before 23:59 PST) + // Let me adjust: Jan 11 03:00 EST = Jan 11 00:00 PST (after range) + let nyStadium = makeStadium(city: "New York", latitude: 40.7128, longitude: -74.0060) + + var estComponents = DateComponents() + estComponents.year = 2026 + estComponents.month = 1 + estComponents.day = 11 + estComponents.hour = 3 + estComponents.minute = 0 + estComponents.timeZone = TimeZone(identifier: "America/New_York")! + let gameTime = pstCalendar.date(from: estComponents)! + + let game = makeGame(stadiumId: nyStadium.id, dateTime: gameTime) + + let result = plan( + games: [game], + stadiums: [nyStadium], + dateRange: dateRange + ) + + // Game should be excluded (after PST range end) + #expect(result.failure?.reason == .noGamesInRange) + } }