Se l'operatore è in ritardo deve ancora trovare la gara nell'app: restano in hub per tutta la giornata e, nei tornei aperti, fino alla fine dell'evento. Co-authored-by: Cursor <cursoragent@cursor.com>
70 lines
2.5 KiB
Swift
70 lines
2.5 KiB
Swift
import Foundation
|
|
|
|
enum ApiInstant {
|
|
static func parse(_ raw: String?) -> Date? {
|
|
let value = raw?.trimmingCharacters(in: .whitespacesAndNewlines) ?? ""
|
|
guard !value.isEmpty else { return nil }
|
|
if let date = formatter.date(from: value) ?? fallbackFormatter.date(from: value) {
|
|
return date
|
|
}
|
|
let normalized = value.replacingOccurrences(of: " ", with: "T")
|
|
if normalized != value {
|
|
return formatter.date(from: normalized) ?? fallbackFormatter.date(from: normalized)
|
|
}
|
|
return ISO8601DateFormatter().date(from: value)
|
|
}
|
|
|
|
static func isScheduledFuture(_ raw: String?, now: Date = Date()) -> Bool {
|
|
guard let date = parse(raw) else { return false }
|
|
return date > now
|
|
}
|
|
|
|
static func isScheduledOnCalendar(_ raw: String?, now: Date = Date()) -> Bool {
|
|
guard let date = parse(raw) else { return false }
|
|
var calendar = Calendar(identifier: .gregorian)
|
|
calendar.timeZone = TimeZone(identifier: "Europe/Rome") ?? .current
|
|
let startOfToday = calendar.startOfDay(for: now)
|
|
return date >= startOfToday
|
|
}
|
|
|
|
static func formatMatchDate(_ raw: String?) -> String? {
|
|
guard let date = parse(raw) else { return nil }
|
|
let f = DateFormatter()
|
|
f.locale = Locale(identifier: "it_IT")
|
|
f.dateFormat = "EEE d MMM yyyy · HH:mm"
|
|
return f.string(from: date)
|
|
}
|
|
|
|
private static let formatter: ISO8601DateFormatter = {
|
|
let f = ISO8601DateFormatter()
|
|
f.formatOptions = [.withInternetDateTime, .withFractionalSeconds]
|
|
return f
|
|
}()
|
|
|
|
private static let fallbackFormatter: ISO8601DateFormatter = {
|
|
let f = ISO8601DateFormatter()
|
|
f.formatOptions = [.withInternetDateTime]
|
|
return f
|
|
}()
|
|
|
|
static let decoder: JSONDecoder = {
|
|
let d = JSONDecoder()
|
|
d.keyDecodingStrategy = .convertFromSnakeCase
|
|
d.dateDecodingStrategy = .custom { decoder in
|
|
let container = try decoder.singleValueContainer()
|
|
let value = try container.decode(String.self)
|
|
if let date = formatter.date(from: value) ?? fallbackFormatter.date(from: value) {
|
|
return date
|
|
}
|
|
throw DecodingError.dataCorruptedError(in: container, debugDescription: "Invalid date: \(value)")
|
|
}
|
|
return d
|
|
}()
|
|
|
|
static let encoder: JSONEncoder = {
|
|
let e = JSONEncoder()
|
|
e.keyEncodingStrategy = .convertToSnakeCase
|
|
return e
|
|
}()
|
|
}
|