mirror of
https://github.com/tonytins/amtkstat.git
synced 2026-10-24 05:32:54 -04:00
Add timezone-aware station lookup and formatting
These changes ensure displayed times respect the station's timezone. Something I mistakenly overlooked when creating this. Luckily, my screenshot with Ashland isn't affected by this change.
This commit is contained in:
parent
fc45303761
commit
dd50d7cd4a
3 changed files with 42 additions and 19 deletions
|
|
@ -7,6 +7,12 @@ enum AmtrakError: Error {
|
|||
case stationNotFound(String)
|
||||
}
|
||||
|
||||
|
||||
struct TrainStationLookUp: Sendable {
|
||||
var trainNumbers: [String]
|
||||
var timeZone: TimeZone?
|
||||
}
|
||||
|
||||
struct AmtrakClient {
|
||||
var decoder = JSONDecoder()
|
||||
|
||||
|
|
@ -42,14 +48,20 @@ struct AmtrakClient {
|
|||
.map(String.init) ?? trainId
|
||||
}
|
||||
|
||||
func fetchStationTrainNumbers(stationCode code: String) async throws -> [String] {
|
||||
|
||||
func trainStationLookup(stationCode code: String) async throws -> TrainStationLookUp {
|
||||
let reponse = try await fetchStation(code: code)
|
||||
|
||||
guard let meta = reponse[code] else {
|
||||
throw AmtrakError.stationNotFound(code)
|
||||
}
|
||||
|
||||
return Array(Set(meta.trains.map(trainNumber(fromTrainId:))))
|
||||
let trainNumbers = Array(Set(meta.trains.map(trainNumber(fromTrainId:))))
|
||||
let timeZone = meta.tz.flatMap(TimeZone.init(identifier:))
|
||||
return TrainStationLookUp(
|
||||
trainNumbers: trainNumbers,
|
||||
timeZone: timeZone
|
||||
)
|
||||
}
|
||||
|
||||
func get<T: Decodable>(_ urlString: String) async throws -> T {
|
||||
|
|
|
|||
|
|
@ -26,12 +26,12 @@ struct AmtrakDateFormatting {
|
|||
return isoFormatter.date(from: isoString)
|
||||
}
|
||||
|
||||
func time(from isoString: String?) -> String? {
|
||||
func time(from isoString: String?, timeZone: TimeZone? = nil) -> String? {
|
||||
guard let isoString, !isoString.isEmpty, let date = isoFormatter.date(
|
||||
from: isoString) else {
|
||||
return nil
|
||||
}
|
||||
|
||||
timeFormatter.timeZone = timeZone
|
||||
return timeFormatter.string(from: date)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ struct ContentView: View {
|
|||
Task {
|
||||
await loadTrainStatus(forStationCode: normalizedStationCode)
|
||||
}
|
||||
}.disabled(normalizedStationCode.isEmpty || isLoading)
|
||||
}.disabled(normalizedStationCode.isEmpty)
|
||||
}.padding(10)
|
||||
|
||||
// Most popular Virtual Railfan stations
|
||||
|
|
@ -104,6 +104,12 @@ struct ContentView: View {
|
|||
}
|
||||
}
|
||||
|
||||
func loadStationStatus(forStationCode code: String) async {
|
||||
guard !code.isEmpty else {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func loadTrainStatus(forStationCode code: String) async {
|
||||
guard !code.isEmpty else {
|
||||
return
|
||||
|
|
@ -115,25 +121,32 @@ struct ContentView: View {
|
|||
defer { isLoading = false }
|
||||
|
||||
do {
|
||||
let trainNumbers = try await client.fetchStationTrainNumbers(
|
||||
let lookup = try await client.trainStationLookup(
|
||||
stationCode: code,
|
||||
)
|
||||
|
||||
guard !trainNumbers.isEmpty else {
|
||||
guard !lookup.trainNumbers.isEmpty else {
|
||||
errorMessage = "\(code) has no trains listed right now"
|
||||
rows = []
|
||||
return
|
||||
}
|
||||
|
||||
var newRows: [TrainStatusRow] = []
|
||||
for number in trainNumbers {
|
||||
for number in lookup.trainNumbers {
|
||||
let trains = try await client.fetchAllTrainStatus(num: number)
|
||||
for train in trains {
|
||||
let platform = train.stations?.first(
|
||||
where: { $0.code == code
|
||||
},
|
||||
)?.platform
|
||||
newRows.append(trainStatus(for: train, atStationCode: code))
|
||||
newRows
|
||||
.append(
|
||||
trainStatus(
|
||||
for: train,
|
||||
atStationCode: code,
|
||||
timeZone: lookup.timeZone
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -170,18 +183,16 @@ struct ContentView: View {
|
|||
}
|
||||
}
|
||||
|
||||
func trainStatus(for train: Train, atStationCode code: String) -> TrainStatusRow {
|
||||
func trainStatus(for train: Train, atStationCode code: String, timeZone: TimeZone?) -> TrainStatusRow {
|
||||
let leg = train.stations?.first { $0.code == code }
|
||||
let amtrakDate = AmtrakDateFormatting()
|
||||
let stationName = leg?.name ?? unknown
|
||||
let arrival = amtrakDate.time(from: leg?.arr) ?? amtrakDate.time(
|
||||
from: leg?.schArr
|
||||
)
|
||||
let depature = amtrakDate.time(from: leg?.dep) ?? amtrakDate.time(
|
||||
from: leg?.schDep
|
||||
)
|
||||
|
||||
currentStation = "\(stationName) station"
|
||||
let arrival = amtrakDate.time(from: leg?.arr, timeZone: timeZone) ?? amtrakDate.time(
|
||||
from: leg?.schArr,
|
||||
timeZone: timeZone)
|
||||
let depature = amtrakDate.time(from: leg?.dep, timeZone: timeZone) ?? amtrakDate.time(
|
||||
from: leg?.schDep,
|
||||
timeZone: timeZone)
|
||||
|
||||
return TrainStatusRow(
|
||||
trainID: train.trainID,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue