extension Duration { struct MatchFormatStyle: DiscreteFormatStyle, Sendable { let periodLength: Int let overtime: Int func format(_ value: Duration) -> String { let current: Int = ((periodLength + overtime) * 60 + Int(value.components.seconds)) / 60 if current > periodLength { return "\(periodLength)' (+\(current - periodLength))" } else { return "\(current)'" } } func discreteInput(before input: Duration) -> Duration? { let minutes: Int64 = input.components.seconds / 60 let value: Duration = .seconds(minutes * 60 - 1) return value } func discreteInput(after input: Duration) -> Duration? { let minutes: Int64 = input.components.seconds / 60 guard minutes != 0 else { return input.components.attoseconds < .zero ? .zero : .seconds(60) } let value: Duration = .seconds((minutes + 1) * 60) return value } } } extension FormatStyle where Self == Duration.MatchFormatStyle { static func matchTime(currentTime: Int, periodLength: Int) -> Duration.MatchFormatStyle { return Duration.MatchFormatStyle(periodLength: periodLength, overtime: max(currentTime - periodLength, .zero)) } }