DateComponentsFormatter
You have a number of seconds representing an amount of time. Not a timestamp, but a duration.
How would you turn 478 seconds into 00:07:58? Or 47478 seconds into 13:11:18?
Like many before you…
func myTimeFormatter(timeInSec: Int) -> String {
let hours: Int = timeInSec / 3600
let hoursRemainder: Int = timeInSec % 3600
let minutes: Int = hoursRemainder / 60
let minsRemainder: Int = hoursRemainder % 60
let seconds: Int = minsRemainder % 60
return String(format: "%02d:%02d:%02d", hours, minutes, seconds)
}
myTimeFormatter(timeInSec: 478) // 00:07:58
It works - 00:07:58 - but with 5 magic variables, and several assumptions on padding and units.
I’m willing to bet programmers across the verse have written this many times.
Or Use DateComponentsFormatter
let defaultFormatter = DateComponentsFormatter()
defaultFormatter.string(from: 478)
// 7:58
Wait … that’s not even close. There’s no leading zeros. I need those - design requires them for alignment, and to make it clear its not 7 hours 58 minutes or something.
So I should continue to build my own formatter, yes?
Don’t worry, we have options
let withPaddingFormatter = DateComponentsFormatter()
withPaddingFormatter.allowedUnits = [.hour,.minute,.second]
withPaddingFormatter.zeroFormattingBehavior = .pad
withPaddingFormatter.string(from: 478)
//00:07:58
We can be specific on the units we want, and set padding behaviour to keep leading zeros, design dependent.
This is still less custom formatting.
But what about… ?
Actually, I also need something like 7m 58s. Or maybe 7 min 58s?
What if I need to show a remaining time?
What if I need it in a more natural language?
let withTextFormatter = DateComponentsFormatter()
//can include days, months also
withTextFormatter.allowedUnits = [.hour,.minute,.second]
withTextFormatter.unitsStyle = .abbreviated
withTextFormatter.string(from: 478)
//7m, 58s
withTextFormatter.unitsStyle = .brief
withTextFormatter.string(from: 478)
//7min, 58seconds
withTextFormatter.unitsStyle = .full
withTextFormatter.string(from: 478)
//7 minutes, 58 seconds
withTextFormatter.unitsStyle = .spellOut
withTextFormatter.string(from: 478)
//"seven minutes, fifty-eight seconds"
withTextFormatter.unitsStyle = .abbreviated
withTextFormatter.includesApproximationPhrase = true
withTextFormatter.includesTimeRemainingPhrase = true
withTextFormatter.string(from: 478)
//About 7m 58s remaining