initial commit

This commit is contained in:
Jon Vanvik 2026-05-31 14:11:29 +02:00
commit 8de962eeb8
44 changed files with 4843 additions and 0 deletions

52
MongoTimestamp.swift Normal file
View file

@ -0,0 +1,52 @@
import Foundation
/// Parses and renders MCMS timestamps. MCMS emits UTC timestamps with a literal
/// space (e.g. `2026-05-04 21:51:57.394127`), so `ISO8601DateFormatter` will not
/// parse them. Try microsecond precision first, then seconds (field guide
/// §3.7 / §8.5). The `en_US_POSIX` locale forces stable parse rules regardless
/// of the device's 12/24-hour setting.
enum MongoTimestamp {
private static let withMicroseconds = parser("yyyy-MM-dd HH:mm:ss.SSSSSS")
private static let seconds = parser("yyyy-MM-dd HH:mm:ss")
private static func parser(_ format: String) -> DateFormatter {
let f = DateFormatter()
f.locale = Locale(identifier: "en_US_POSIX")
f.timeZone = TimeZone(identifier: "UTC")
f.dateFormat = format
return f
}
static func date(from string: String) -> Date? {
withMicroseconds.date(from: string) ?? seconds.date(from: string)
}
/// Human duration between two MCMS timestamps e.g. uptime computed as
/// (device state `Time` `Online Time`), so it uses the device's own clock
/// rather than the phone's. Returns nil if either is unparseable or end < start.
static func duration(from startString: String?, to endString: String?) -> String? {
guard let startString, let start = date(from: startString),
let endString, let end = date(from: endString) else { return nil }
let total = Int(end.timeIntervalSince(start))
guard total >= 0 else { return nil }
let days = total / 86400, hours = (total % 86400) / 3600, mins = (total % 3600) / 60
if days > 0 { return "\(days)d \(hours)h" }
if hours > 0 { return "\(hours)h \(mins)m" }
return "\(mins)m"
}
private static let display: DateFormatter = {
let f = DateFormatter()
f.dateStyle = .medium
f.timeStyle = .short
return f
}()
/// Render a raw MCMS timestamp in the device's locale/zone, falling back to
/// the original string if it doesn't parse.
static func displayString(_ string: String?) -> String? {
guard let string else { return nil }
guard let date = date(from: string) else { return string }
return display.string(from: date)
}
}