13

I am writing a racing app and want to convert a large number of milliseconds into minutes:seconds.milliseconds (for example, 1:32.361). At the moment I just do it through maths (minutes / 60000), then get remainder and divide further, etc., but i find that it is off every now and then by 1 millisecond. I know this might not sound like a big deal, but I tried to find the average of 1:32.004 and 1:32.004 and it returned 1:32.003, which means it gets put in incorrectly and the rest of the app can't deal with it.

Is there a way to use NSDate or NSDateFormatter or something like that to format the milliseconds into MM:ss.mmm?

I have looked at these sources but not found the answer:

How to convert milliseconds into minutes?
Convert seconds into minutes and seconds
Convert milliseconds to minutes
http://www.codingexplorer.com/swiftly-getting-human-readable-date-nsdateformatter/

Leo Dabus
  • 229,809
  • 59
  • 489
  • 571
Matt Kelly
  • 1,451
  • 2
  • 13
  • 30
  • Without seeing your code it is difficult to judge why you get an imprecise result "every now and then" ... How are the milliseconds represented (as an integer or floating point number)? How do you convert? How to you compute the average? – Martin R Jun 11 '15 at 04:55
  • I have a similar problem, and I have discovered `DateComponentsFormatter` which l doesn't support formatting milliseconds, which seems rather odd to me. (nor allow for arbitrary zero padding). It might be useful for somebody with a similar problems – Gavin May 14 '22 at 12:27

1 Answers1

45

You can create a TimeInterval extension to format your elapsed time as follow:

Xcode 11.4 • Swift 5.2 or later

extension TimeInterval {
    var hourMinuteSecondMS: String {
        String(format:"%d:%02d:%02d.%03d", hour, minute, second, millisecond)
    }
    var minuteSecondMS: String {
        String(format:"%d:%02d.%03d", minute, second, millisecond)
    }
    var hour: Int {
        Int((self/3600).truncatingRemainder(dividingBy: 3600))
    }
    var minute: Int {
        Int((self/60).truncatingRemainder(dividingBy: 60))
    }
    var second: Int {
        Int(truncatingRemainder(dividingBy: 60))
    }
    var millisecond: Int {
        Int((self*1000).truncatingRemainder(dividingBy: 1000))
    }
}

extension Int {
    var msToSeconds: Double { Double(self) / 1000 }
}

let seconds = 131.531   // 131.531
let time = seconds.minuteSecondMS  //  "2:11.531"
let millisecond = seconds.millisecond    // 531

let ms = 1111
let sec = ms.msToSeconds.minuteSecondMS   // "0:01.111"

Date().description(with: .current)        // "Wednesday, October 21, 2020 at 5:44:51 PM Brasilia Standard Time"
let startOfDay = Calendar.current.startOfDay(for: Date())
let secondsFromStartOfDay = Date().timeIntervalSinceReferenceDate - startOfDay.timeIntervalSinceReferenceDate
secondsFromStartOfDay.hourMinuteSecondMS  // "17:44:51.705"
Leo Dabus
  • 229,809
  • 59
  • 489
  • 571