Formatting a Duration with NSDateComponentsFormatter

Recently I have been adding extra translations to Streaks Workout, which means ensuring that in addition to everything being translated for each language, dates and numbers need to appear correctly.

During a workout, the total elapsed time is displayed so the user can see how long their workout has gone for. For example, two minutes 30 seconds is displayed as:


Previously, this string was calculated using the following code:

let duration: NSTimeInterval = 150 // 2 minutes, 30 seconds

let s: Int = Int(duration) % 60
let m: Int = Int(duration) / 60

let formattedDuration = String(format: "%0d:%02d", m, s)

This means that the seconds value will always be zero-padding to two digits, while the minutes will be zero-padded to one digit. This means that, say, 5 seconds would be displayed as 0:05, not as 5 or 0:5.

In some Arabic-speaking countries, 2 minutes 3 seconds would be displayed as ٢:٣٠. In fact, I'm not even sure if all countries separate the minutes and seconds count using a colon (:).

Using NSDateComponentsFormatter (available since iOS 8.0), we don't need to worry either about the separator nor the type of digits used. The above code can be replaced as follows, to handle all countries equally and in the same style:

let duration: NSTimeInterval = 150 // 2 minutes, 30 seconds

let formatter = NSDateComponentsFormatter()
formatter.unitsStyle = .Positional
formatter.allowedUnits = [ .Minute, .Second ]
formatter.zeroFormattingBehavior = [ .Pad ]

let formattedDuration = formatter.stringFromTimeInterval(duration)

The .Positional value for unitsStyle specifies that the 0:00 style should be used (as opposed to, say, .Abbreviated which would be 0h 0m.

The zeroFormattingBehavior variable indicates how zeroes should be treated. In this case, we want them displayed, so the .Pad option is used to make this happen.

Note: In this example, we could instead use an instance of NSDateComponents to specify the number of minutes and seconds, since NSDateComponentsFormatter also has a method called stringFromDateComponents.

For more information about NSDateComponentsFormatter, refer to the Apple NSDateComponentsFormatter Documentation.