Home > Back-end >  Formatting milliseconds with a Timer in Swift and SwiftUI
Formatting milliseconds with a Timer in Swift and SwiftUI

Time:03-27

I have this function which can successfully convert a counter variable into a beautifully formatted minutes and seconds string. How can I extend this to a format displaying MM:SS:milliseconds ?

I thought perhaps to do let milliseconds = Int(Double(seconds / 60) * 100) and append it to the return. Any tips?

Note: my timer should be publishing with enough granularity @State var timer = Timer.publish(every: 0.1, on: .main, in: .common).autoconnect()

func formatMmSs(counter: Double) -> String {
    let minutes = Int(counter) / 60 % 60
    let seconds = Int(counter) % 60
    return String(format: "i:i", minutes, seconds)
}

CodePudding user response:

This is keep using your approach also following Leo approach,

func formatMmSs(counter: Double) -> String {
    let minutes = Int(counter) / 60 % 60
    let seconds = Int(counter) % 60
    let milliseconds = Int(counter*1000) % 1000
    return String(format: "d:d:d", minutes, seconds, milliseconds)
}

CodePudding user response:

You just need to multiply your counter (number of seconds) times 1000, truncating remainder dividing by 1000 and coerce the result to integer:

func formatMmSsMl(counter: Double) -> String {
    let minutes = Int((counter/60).truncatingRemainder(dividingBy: 60))
    let seconds = Int(counter.truncatingRemainder(dividingBy: 60))
    let milliseconds = Int((counter*1000).truncatingRemainder(dividingBy: 1000))
    return String(format: "d:d.d", minutes, seconds, milliseconds)
}

Or implemented as a computed property for BinaryFloatingPoint types:

extension BinaryFloatingPoint {
    var intValue: Int { Int(self) }
    var minutesSecondsMilliseconds: String {
        String(format: "d:d.d",
               (self / 60).truncatingRemainder(dividingBy: 60).intValue,
               truncatingRemainder(dividingBy: 60).intValue,
               (self * 1000).truncatingRemainder(dividingBy: 1000).intValue)
    }
}

You can also custom format the floating point. No need to coerce to integer as follow:

extension TimeInterval {
    var minutesSecondsMilliseconds: String {
        String(format: ".0f:.0f..0f",
               (self / 60).truncatingRemainder(dividingBy: 60),
               truncatingRemainder(dividingBy: 60),
               (self * 1000).truncatingRemainder(dividingBy: 1000).rounded(.down))
    }
}

123.45678.minutesSecondsMilliseconds   // "02:03.456"
  • Related