From 3533e5d4b8b9a1300fccb5122057d9b68b62beca Mon Sep 17 00:00:00 2001 From: Tony Bark <35226681+tonytins@users.noreply.github.com> Date: Sun, 23 Aug 2026 20:32:33 -0400 Subject: [PATCH] Train status now properly gives minutes (or hours) a train is early or late - Convert AmtrakDateFormatting API from static to instance properties/methods and added parsedDate(from:) to return Date. - Update time(from:) and date(from:) to instance methods. Improve isOnTime logic to compute actual vs scheduled differences (minutes/hours) and report early/late/on-time. - Updated ContentView to create an AmtrakDateFormatting instance and use the new API. Remove the Train.serviceDate extension. --- .../AmtrakStatus/AmtrakDateFormatting.swift | 19 ++++++++--- Sources/AmtrakStatus/ContentView.swift | 34 ++++++++++++------- 2 files changed, 35 insertions(+), 18 deletions(-) diff --git a/Sources/AmtrakStatus/AmtrakDateFormatting.swift b/Sources/AmtrakStatus/AmtrakDateFormatting.swift index 912c9c7..e0e9c86 100644 --- a/Sources/AmtrakStatus/AmtrakDateFormatting.swift +++ b/Sources/AmtrakStatus/AmtrakDateFormatting.swift @@ -1,23 +1,32 @@ import Foundation struct AmtrakDateFormatting { - static let isoFormatter = ISO8601DateFormatter() + let isoFormatter = ISO8601DateFormatter() - static let timeFormatter: DateFormatter = { + let timeFormatter: DateFormatter = { let formatter = DateFormatter() formatter.dateStyle = .none formatter.timeStyle = .short return formatter }() - static let dateFormatter: DateFormatter = { + let dateFormatter: DateFormatter = { let formatter = DateFormatter() formatter.dateStyle = .medium formatter.timeStyle = .none return formatter }() - static func time(from isoString: String?) -> String? { + 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?) -> String? { guard let isoString, !isoString.isEmpty, let date = isoFormatter.date( from: isoString) else { return nil @@ -26,7 +35,7 @@ struct AmtrakDateFormatting { return timeFormatter.string(from: date) } - static func date(from isoString: String?) -> String? { + func date(from isoString: String?) -> String? { guard let isoString, !isoString.isEmpty, let date = isoFormatter.date( from: isoString) else { return nil diff --git a/Sources/AmtrakStatus/ContentView.swift b/Sources/AmtrakStatus/ContentView.swift index f99a591..4defdcb 100644 --- a/Sources/AmtrakStatus/ContentView.swift +++ b/Sources/AmtrakStatus/ContentView.swift @@ -1,11 +1,6 @@ import SwiftCrossUI import Foundation -extension Train { - var serviceDate: String { - AmtrakDateFormatting.date(from: createdAt) ?? "-" - } -} struct ContentView: View { @State var client = AmtrakClient() @@ -137,23 +132,36 @@ struct ContentView: View { func isOnTime(arr: String?, schArr: String?) -> String { let amtrakDate = AmtrakDateFormatting() - if AmtrakDateFormatting - .time(from: arr) != AmtrakDateFormatting - .time(from: schArr) { - return "Late" + guard + let actualDate = amtrakDate.parsedDate(from: arr), + let scheduledDate = amtrakDate.parsedDate(from: schArr) + else { + return "On Time" } - return "On Time" + let differenceInMinutes = Int(actualDate.timeIntervalSince(scheduledDate) / 60) + + switch differenceInMinutes { + case -1...1: + return "On Time" + case ..<0: + return "\(-differenceInMinutes) min early" + case 0..<60: + return "\(differenceInMinutes) min late" + default: + let hours = differenceInMinutes / 60 + return "\(hours) hr late" + } } func trainStatus(for train: Train, atStationCode code: String) -> TrainStatusRow { let leg = train.stations?.first { $0.code == code } - let platform = leg?.platform ?? "-" + let amtrakDate = AmtrakDateFormatting() let stationName = leg?.name ?? unknown - let arrival = AmtrakDateFormatting.time(from: leg?.arr) ?? AmtrakDateFormatting.time( + let arrival = amtrakDate.time(from: leg?.arr) ?? amtrakDate.time( from: leg?.schArr ) - let depature = AmtrakDateFormatting.time(from: leg?.dep) ?? AmtrakDateFormatting.time( + let depature = amtrakDate.time(from: leg?.dep) ?? amtrakDate.time( from: leg?.schDep )