amtkstat/Sources/AmtrakStatus/AmtrakDateFormatting.swift
Tony Bark e0077ec13b Centralize lateness logic
- I finally put the app in the Travel category. xD
- I also moved the train lateness and arrival calculations into AmtrakDateFormatting from ContentView. I also renamed the timezone formatting parameters for clarity.
2026-08-24 21:05:11 -04:00

93 lines
2.6 KiB
Swift

import Foundation
struct AmtrakDateFormatting {
let isoFormatter = ISO8601DateFormatter()
let timeFormatter: DateFormatter = {
let formatter = DateFormatter()
formatter.dateStyle = .none
formatter.timeStyle = .short
return formatter
}()
let dateFormatter: DateFormatter = {
let formatter = DateFormatter()
formatter.dateStyle = .medium
formatter.timeStyle = .none
return formatter
}()
func parsedDate(from isoString: String?) -> Date? {
guard let isoString, !isoString.isEmpty, let date = isoFormatter.date(
from: isoString) else {
return nil
}
return isoFormatter.date(from: isoString)
}
func time(from isoString: String?, in zone: TimeZone?, comparedTo originZone: TimeZone? = nil) -> String? {
guard let isoString, !isoString.isEmpty, let date = isoFormatter.date(
from: isoString) else {
return nil
}
timeFormatter.timeZone = zone
let formatted = timeFormatter.string(from: date)
guard
let zone,
let originZone,
zone.identifier != originZone.identifier,
let abbreviation = zone.abbreviation(for: date)
else {
return formatted
}
return "\(formatted) \(abbreviation)"
}
func isOnTime(actual: String?, scheduled: String?) -> TrainLateness {
guard
let actualDate = parsedDate(from: actual),
let scheduledDate = parsedDate(from: scheduled)
else {
return .unknown
}
let differenceInMinutes = Int(actualDate.timeIntervalSince(scheduledDate) / 60)
switch differenceInMinutes {
case -1...1:
return .onTime
case ..<0:
return .early(minutes: -differenceInMinutes)
default:
return .late(minutes: differenceInMinutes)
}
}
func localTime(timeZone: TimeZone?) -> String {
let now = Date()
timeFormatter.timeZone = timeZone
return timeFormatter.string(from: now)
}
func updateTime(timeZone: TimeZone?) {
let now = Date()
timeFormatter.timeZone = timeZone
}
func date(from isoString: String?) -> String? {
guard let isoString, !isoString.isEmpty, let date = isoFormatter.date(
from: isoString) else {
return nil
}
return dateFormatter.string(from: date)
}
}