feat: add timezone support for stadium-local game times
Adds timeZoneIdentifier to Stadium model and localGameTime/localGameTimeShort computed properties to RichGame. Game times can now display in venue local timezone. Also adds timezone field to Python StadiumInfo dataclass with example entries for Pacific, Central, Mountain, and Toronto timezones. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -42,6 +42,7 @@ class StadiumInfo:
|
|||||||
sport: str
|
sport: str
|
||||||
latitude: float
|
latitude: float
|
||||||
longitude: float
|
longitude: float
|
||||||
|
timezone: str = "America/New_York" # IANA timezone identifier
|
||||||
|
|
||||||
|
|
||||||
# Hardcoded stadium mappings
|
# Hardcoded stadium mappings
|
||||||
@@ -55,10 +56,10 @@ STADIUM_MAPPINGS: dict[str, dict[str, StadiumInfo]] = {
|
|||||||
"stadium_nba_united_center": StadiumInfo("stadium_nba_united_center", "United Center", "Chicago", "IL", "USA", "nba", 41.8807, -87.6742),
|
"stadium_nba_united_center": StadiumInfo("stadium_nba_united_center", "United Center", "Chicago", "IL", "USA", "nba", 41.8807, -87.6742),
|
||||||
"stadium_nba_rocket_mortgage_fieldhouse": StadiumInfo("stadium_nba_rocket_mortgage_fieldhouse", "Rocket Mortgage FieldHouse", "Cleveland", "OH", "USA", "nba", 41.4965, -81.6882),
|
"stadium_nba_rocket_mortgage_fieldhouse": StadiumInfo("stadium_nba_rocket_mortgage_fieldhouse", "Rocket Mortgage FieldHouse", "Cleveland", "OH", "USA", "nba", 41.4965, -81.6882),
|
||||||
"stadium_nba_american_airlines_center": StadiumInfo("stadium_nba_american_airlines_center", "American Airlines Center", "Dallas", "TX", "USA", "nba", 32.7905, -96.8103),
|
"stadium_nba_american_airlines_center": StadiumInfo("stadium_nba_american_airlines_center", "American Airlines Center", "Dallas", "TX", "USA", "nba", 32.7905, -96.8103),
|
||||||
"stadium_nba_ball_arena": StadiumInfo("stadium_nba_ball_arena", "Ball Arena", "Denver", "CO", "USA", "nba", 39.7487, -105.0077),
|
"stadium_nba_ball_arena": StadiumInfo("stadium_nba_ball_arena", "Ball Arena", "Denver", "CO", "USA", "nba", 39.7487, -105.0077, "America/Denver"),
|
||||||
"stadium_nba_little_caesars_arena": StadiumInfo("stadium_nba_little_caesars_arena", "Little Caesars Arena", "Detroit", "MI", "USA", "nba", 42.3411, -83.0553),
|
"stadium_nba_little_caesars_arena": StadiumInfo("stadium_nba_little_caesars_arena", "Little Caesars Arena", "Detroit", "MI", "USA", "nba", 42.3411, -83.0553),
|
||||||
"stadium_nba_chase_center": StadiumInfo("stadium_nba_chase_center", "Chase Center", "San Francisco", "CA", "USA", "nba", 37.7680, -122.3877),
|
"stadium_nba_chase_center": StadiumInfo("stadium_nba_chase_center", "Chase Center", "San Francisco", "CA", "USA", "nba", 37.7680, -122.3877, "America/Los_Angeles"),
|
||||||
"stadium_nba_toyota_center": StadiumInfo("stadium_nba_toyota_center", "Toyota Center", "Houston", "TX", "USA", "nba", 29.7508, -95.3621),
|
"stadium_nba_toyota_center": StadiumInfo("stadium_nba_toyota_center", "Toyota Center", "Houston", "TX", "USA", "nba", 29.7508, -95.3621, "America/Chicago"),
|
||||||
"stadium_nba_gainbridge_fieldhouse": StadiumInfo("stadium_nba_gainbridge_fieldhouse", "Gainbridge Fieldhouse", "Indianapolis", "IN", "USA", "nba", 39.7640, -86.1555),
|
"stadium_nba_gainbridge_fieldhouse": StadiumInfo("stadium_nba_gainbridge_fieldhouse", "Gainbridge Fieldhouse", "Indianapolis", "IN", "USA", "nba", 39.7640, -86.1555),
|
||||||
"stadium_nba_intuit_dome": StadiumInfo("stadium_nba_intuit_dome", "Intuit Dome", "Inglewood", "CA", "USA", "nba", 33.9425, -118.3417),
|
"stadium_nba_intuit_dome": StadiumInfo("stadium_nba_intuit_dome", "Intuit Dome", "Inglewood", "CA", "USA", "nba", 33.9425, -118.3417),
|
||||||
"stadium_nba_cryptocom_arena": StadiumInfo("stadium_nba_cryptocom_arena", "Crypto.com Arena", "Los Angeles", "CA", "USA", "nba", 34.0430, -118.2673),
|
"stadium_nba_cryptocom_arena": StadiumInfo("stadium_nba_cryptocom_arena", "Crypto.com Arena", "Los Angeles", "CA", "USA", "nba", 34.0430, -118.2673),
|
||||||
@@ -75,8 +76,8 @@ STADIUM_MAPPINGS: dict[str, dict[str, StadiumInfo]] = {
|
|||||||
"stadium_nba_moda_center": StadiumInfo("stadium_nba_moda_center", "Moda Center", "Portland", "OR", "USA", "nba", 45.5316, -122.6668),
|
"stadium_nba_moda_center": StadiumInfo("stadium_nba_moda_center", "Moda Center", "Portland", "OR", "USA", "nba", 45.5316, -122.6668),
|
||||||
"stadium_nba_golden_1_center": StadiumInfo("stadium_nba_golden_1_center", "Golden 1 Center", "Sacramento", "CA", "USA", "nba", 38.5802, -121.4997),
|
"stadium_nba_golden_1_center": StadiumInfo("stadium_nba_golden_1_center", "Golden 1 Center", "Sacramento", "CA", "USA", "nba", 38.5802, -121.4997),
|
||||||
"stadium_nba_frost_bank_center": StadiumInfo("stadium_nba_frost_bank_center", "Frost Bank Center", "San Antonio", "TX", "USA", "nba", 29.4270, -98.4375),
|
"stadium_nba_frost_bank_center": StadiumInfo("stadium_nba_frost_bank_center", "Frost Bank Center", "San Antonio", "TX", "USA", "nba", 29.4270, -98.4375),
|
||||||
"stadium_nba_scotiabank_arena": StadiumInfo("stadium_nba_scotiabank_arena", "Scotiabank Arena", "Toronto", "ON", "Canada", "nba", 43.6435, -79.3791),
|
"stadium_nba_scotiabank_arena": StadiumInfo("stadium_nba_scotiabank_arena", "Scotiabank Arena", "Toronto", "ON", "Canada", "nba", 43.6435, -79.3791, "America/Toronto"),
|
||||||
"stadium_nba_delta_center": StadiumInfo("stadium_nba_delta_center", "Delta Center", "Salt Lake City", "UT", "USA", "nba", 40.7683, -111.9011),
|
"stadium_nba_delta_center": StadiumInfo("stadium_nba_delta_center", "Delta Center", "Salt Lake City", "UT", "USA", "nba", 40.7683, -111.9011, "America/Denver"),
|
||||||
"stadium_nba_capital_one_arena": StadiumInfo("stadium_nba_capital_one_arena", "Capital One Arena", "Washington", "DC", "USA", "nba", 38.8981, -77.0209),
|
"stadium_nba_capital_one_arena": StadiumInfo("stadium_nba_capital_one_arena", "Capital One Arena", "Washington", "DC", "USA", "nba", 38.8981, -77.0209),
|
||||||
},
|
},
|
||||||
"mlb": {
|
"mlb": {
|
||||||
|
|||||||
@@ -91,4 +91,20 @@ struct RichGame: Identifiable, Hashable, Codable {
|
|||||||
var venueDescription: String {
|
var venueDescription: String {
|
||||||
"\(stadium.name), \(stadium.city)"
|
"\(stadium.name), \(stadium.city)"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Game time formatted in the stadium's local timezone with timezone indicator
|
||||||
|
var localGameTime: String {
|
||||||
|
let formatter = DateFormatter()
|
||||||
|
formatter.dateFormat = "h:mm a z"
|
||||||
|
formatter.timeZone = stadium.timeZone ?? .current
|
||||||
|
return formatter.string(from: game.dateTime)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Game time formatted in the stadium's local timezone without timezone indicator
|
||||||
|
var localGameTimeShort: String {
|
||||||
|
let formatter = DateFormatter()
|
||||||
|
formatter.dateFormat = "h:mm a"
|
||||||
|
formatter.timeZone = stadium.timeZone ?? .current
|
||||||
|
return formatter.string(from: game.dateTime)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ struct Stadium: Identifiable, Codable, Hashable {
|
|||||||
let sport: Sport
|
let sport: Sport
|
||||||
let yearOpened: Int?
|
let yearOpened: Int?
|
||||||
let imageURL: URL?
|
let imageURL: URL?
|
||||||
|
let timeZoneIdentifier: String?
|
||||||
|
|
||||||
init(
|
init(
|
||||||
id: String,
|
id: String,
|
||||||
@@ -28,7 +29,8 @@ struct Stadium: Identifiable, Codable, Hashable {
|
|||||||
capacity: Int,
|
capacity: Int,
|
||||||
sport: Sport,
|
sport: Sport,
|
||||||
yearOpened: Int? = nil,
|
yearOpened: Int? = nil,
|
||||||
imageURL: URL? = nil
|
imageURL: URL? = nil,
|
||||||
|
timeZoneIdentifier: String? = nil
|
||||||
) {
|
) {
|
||||||
self.id = id
|
self.id = id
|
||||||
self.name = name
|
self.name = name
|
||||||
@@ -40,6 +42,11 @@ struct Stadium: Identifiable, Codable, Hashable {
|
|||||||
self.sport = sport
|
self.sport = sport
|
||||||
self.yearOpened = yearOpened
|
self.yearOpened = yearOpened
|
||||||
self.imageURL = imageURL
|
self.imageURL = imageURL
|
||||||
|
self.timeZoneIdentifier = timeZoneIdentifier
|
||||||
|
}
|
||||||
|
|
||||||
|
var timeZone: TimeZone? {
|
||||||
|
timeZoneIdentifier.flatMap { TimeZone(identifier: $0) }
|
||||||
}
|
}
|
||||||
|
|
||||||
var location: CLLocation {
|
var location: CLLocation {
|
||||||
|
|||||||
Reference in New Issue
Block a user