SoulReaver313
SoulReaver313

Reputation: 543

How to convert milliseconds to Stopwatch format in Kotlin? (HH:MM:SS)

I have time in milliseconds which i'm getting by:

    val past = System.currentTimeMillis()
    val future = System.currentTimeMillis() + 1000L
    
    // getting duration every second. imagine working stopwatch here
    val duration = future - past
    
    // Imconvert duration to HH:MM:SS

. I need to convert it to stopwatch format (HH:MM:SS). I know there is a lot of options. But what is the most modern and easiest way to do it?

Upvotes: 2

Views: 3157

Answers (2)

Joffrey
Joffrey

Reputation: 37729

Be careful how you get milliseconds in the first place

First and foremost, you should not use System.currentTimeMillis() for elapsed time. This clock is meant for wallclock time and is subject to drifting or leap second adjustments that can mess up your measurements significantly.

A better clock to use would be System.nanoTime(). But in Kotlin you don't need to call it explicitly if you want to measure elapsed time. You can use nice utilities like measureNanoTime, or the experimental measureTime which directly returns a Duration that you can format:

val durationNanos = measureNanoTime {
    // run the code to measure
}

val duration = measureTime {
    // run the code to measure
}

Convert milliseconds to Duration

If you don't want to use measureTime and still have just a number of milliseconds or nanoseconds, you can convert them to a Duration by using one of the extension properties of Duration.Companion:

import kotlin.time.Duration.Companion.milliseconds

val durationMillis: Long = 1000L // got from somewhere
val duration: Duration = durationMillis.milliseconds

However, that is quite awkward and that's the reason why those extensions were deprecated for a while. They were restored because they are nice to use with number literals, but they are not so nice with variable names. Instead, you can use Long.toDuration():

import kotlin.time.*

val durationMillis = 1000L // got from somewhere
val duration = durationMillis.toDuration(DurationUnit.MILLISECONDS)

Format Duration

If you just want a nice visual format, note that the kotlin.time.Duration type is already printed nicely thanks to its nice toString implementation:

import kotlin.time.Duration.Companion.minutes
import kotlin.time.Duration.Companion.seconds
import kotlin.time.Duration.Companion.milliseconds

fun main() {
    val duration = 4.minutes + 67.seconds + 230.milliseconds
    println(duration) // prints 5m 7.23s
}

See it in the playground: https://pl.kotl.in/YUT6FZA0l

If you really want the format you're asking for, you may also use toComponents as @Can_of_awe mentioned:

// example duration, built from extensions on number literals
val duration = 4.minutes + 67.seconds + 230.milliseconds

val durationString = duration.toComponents { hours, minutes, seconds, _ ->
    "%02d:%02d:%02d".format(hours, minutes, seconds)
}
println(durationString) // prints 00:05:07

Upvotes: 9

Can_of_awe
Can_of_awe

Reputation: 1566

A more Kotlin-style straightforward way of doing this:

val durationString = duration.milliseconds.toComponents { hours, minutes, seconds, _ ->
    "%02d:%02d:%02d".format(hours, minutes, seconds)
}

Where the .milliseconds extension is from import kotlin.time.Duration.Companion.milliseconds

Upvotes: 6

Related Questions