时间度量
The Kotlin standard library gives you the tools to calculate and measure time in different units. Accurate time measurement is important for activities like:
- Managing threads or processes
- Collecting statistics
- Detecting timeouts
- Debugging
By default, time is measured using a monotonic time source, but other time sources can be configured. For more information, see Create time source.
Calculate duration
To represent an amount of time, the standard library has the Duration
class. A Duration
can be expressed in the following units from the DurationUnit
enum class:
NANOSECONDS
MICROSECONDS
MILLISECONDS
SECONDS
MINUTES
HOURS
DAYS
A Duration
can be positive, negative, zero, positive infinity, or negative infinity.
Create duration
To create a Duration
, use the extension properties
available for Int
, Long
, and Double
types: nanoseconds
, microseconds
, milliseconds
, seconds
, minutes
,
hours
, and days
.
Days refer to periods of 24 hours. They are not calendar days.
{type = "tip"}
For example:
import kotlin.time.*
import kotlin.time.Duration.Companion.nanoseconds
import kotlin.time.Duration.Companion.milliseconds
import kotlin.time.Duration.Companion.seconds
import kotlin.time.Duration.Companion.minutes
import kotlin.time.Duration.Companion.days
fun main() {
//sampleStart
val fiveHundredMilliseconds: Duration = 500.milliseconds
val zeroSeconds: Duration = 0.seconds
val tenMinutes: Duration = 10.minutes
val negativeNanosecond: Duration = (-1).nanoseconds
val infiniteDays: Duration = Double.POSITIVE_INFINITY.days
val negativeInfiniteDays: Duration = Double.NEGATIVE_INFINITY.days
println(fiveHundredMilliseconds) // 500ms
println(zeroSeconds) // 0s
println(tenMinutes) // 10m
println(negativeNanosecond) // -1ns
println(infiniteDays) // Infinity
println(negativeInfiniteDays) // -Infinity
//sampleEnd
}
You can also perform basic arithmetic with Duration
objects:
import kotlin.time.*
import kotlin.time.Duration.Companion.seconds
fun main() {
//sampleStart
val fiveSeconds: Duration = 5.seconds
val thirtySeconds: Duration = 30.seconds
println(fiveSeconds + thirtySeconds)
// 35s
println(thirtySeconds - fiveSeconds)
// 25s
println(fiveSeconds * 2)
// 10s
println(thirtySeconds / 2)
// 15s
println(thirtySeconds / fiveSeconds)
// 6.0
println(-thirtySeconds)
// -30s
println((-thirtySeconds).absoluteValue)
// 30s
//sampleEnd
}
Get string representation
It can be useful to have a string representation of a Duration
so that you can print, serialize, transfer, or store it.
To get a string representation, use the .toString()
function. By default, the time is reported using each unit that is
present. For example: 1h 0m 45.677s
or -(6d 5h 5m 28.284s)
To configure the output, use the .toString()
function with your desired DurationUnit
and number of decimal places
as function parameters:
import kotlin.time.Duration
import kotlin.time.Duration.Companion.milliseconds
import kotlin.time.DurationUnit
fun main() {
//sampleStart
// Print in seconds with 2 decimal places
println(5887.milliseconds.toString(DurationUnit.SECONDS, 2))
// 5.89s
//sampleEnd
}
To get an ISO-8601-compatible string, use the toIsoString()
function:
import kotlin.time.Duration.Companion.seconds
fun main() {
//sampleStart
println(86420.seconds.toIsoString()) // PT24H0M20S
//sampleEnd
}
Convert duration
To convert your Duration
into a different DurationUnit
, use the following properties:
inWholeNanoseconds
inWholeMicroseconds
inWholeSeconds
inWholeMinutes
inWholeHours
inWholeDays
For example:
import kotlin.time.Duration
import kotlin.time.Duration.Companion.minutes
fun main() {
//sampleStart
val thirtyMinutes: Duration = 30.minutes
println(thirtyMinutes.inWholeSeconds)
// 1800
//sampleEnd
}
Alternatively, you can use your desired DurationUnit
as a function parameter in the following extension functions:
.toInt()
.toDouble()
.toLong()
For example:
import kotlin.time.Duration.Companion.seconds
import kotlin.time.DurationUnit
fun main() {
//sampleStart
println(270.seconds.toDouble(DurationUnit.MINUTES))
// 4.5
//sampleEnd
}
Compare duration
To check if Duration
objects are equal, use the equality operator (==
):
import kotlin.time.Duration
import kotlin.time.Duration.Companion.hours
import kotlin.time.Duration.Companion.minutes
fun main() {
//sampleStart
val thirtyMinutes: Duration = 30.minutes
val halfHour: Duration = 0.5.hours
println(thirtyMinutes == halfHour)
// true
//sampleEnd
}
To compare Duration
objects, use the comparison operators (<
, >
):
import kotlin.time.Duration.Companion.microseconds
import kotlin.time.Duration.Companion.nanoseconds
fun main() {
//sampleStart
println(3000.microseconds < 25000.nanoseconds)
// false
//sampleEnd
}
Break duration into components
To break down a Duration
into its time components and perform a further action, use the overload of the
toComponents()
function.
Add your desired action as a function or lambda expression as a function parameter.
For example:
import kotlin.time.Duration
import kotlin.time.Duration.Companion.minutes
fun main() {
//sampleStart
val thirtyMinutes: Duration = 30.minutes
println(thirtyMinutes.toComponents { hours, minutes, _, _ -> "${hours}h:${minutes}m" })
// 0h:30m
//sampleEnd
}
In this example, the lambda expression has hours
and minutes
as function parameters with underscores (_
) for the
unused seconds
and nanoseconds
parameters. The expression returns a concatenated string using string templates
to get the desired output format of hours
and minutes
.
Measure time
To track the passage of time, the standard library provides tools so that you can easily:
- Measure the time taken to execute some code with your desired time unit.
- Mark a moment in time.
- Compare and subtract two moments in time.
- Check how much time has passed since a specific moment in time.
- Check whether the current time has passed a specific moment in time.
Measure code execution time
To measure the time taken to execute a block of code, use the measureTime
inline function:
import kotlin.time.measureTime
fun main() {
//sampleStart
val timeTaken = measureTime {
Thread.sleep(100)
}
println(timeTaken) // e.g. 103 ms
//sampleEnd
}
To measure the time taken to execute a block of code and return the value of the block of code, use inline function measureTimedValue
.
For example:
import kotlin.time.measureTimedValue
fun main() {
//sampleStart
val (value, timeTaken) = measureTimedValue {
Thread.sleep(100)
42
}
println(value) // 42
println(timeTaken) // e.g. 103 ms
//sampleEnd
}
By default, both functions use a monotonic time source.
Mark moments in time
To mark a specific moment in time, use the TimeSource
interface and the markNow()
function
to create a TimeMark
:
import kotlin.time.*
fun main() {
val timeSource = TimeSource.Monotonic
val mark = timeSource.markNow()
}
Measure differences in time
To measure differences between TimeMark
objects from the same time source, use the subtraction operator (-
).
To compare TimeMark
objects from the same time source, use the comparison operators (<
, >
).
For example:
import kotlin.time.*
fun main() {
//sampleStart
val timeSource = TimeSource.Monotonic
val mark1 = timeSource.markNow()
Thread.sleep(500) // Sleep 0.5 seconds.
val mark2 = timeSource.markNow()
repeat(4) { n ->
val mark3 = timeSource.markNow()
val elapsed1 = mark3 - mark1
val elapsed2 = mark3 - mark2
println("Measurement 1.${n + 1}: elapsed1=$elapsed1, elapsed2=$elapsed2, diff=${elapsed1 - elapsed2}")
}
println(mark2 > mark1) // This is true, as mark2 was captured later than mark1.
// true
//sampleEnd
}
To check if a deadline has passed or a timeout has been reached, use the hasPassedNow()
and hasNotPassedNow()
extension functions:
import kotlin.time.*
import kotlin.time.Duration.Companion.seconds
fun main() {
//sampleStart
val timeSource = TimeSource.Monotonic
val mark1 = timeSource.markNow()
val fiveSeconds: Duration = 5.seconds
val mark2 = mark1 + fiveSeconds
// It hasn't been 5 seconds yet
println(mark2.hasPassedNow())
// false
// Wait six seconds
Thread.sleep(6000)
println(mark2.hasPassedNow())
// true
//sampleEnd
}
Time sources
By default, time is measured using a monotonic time source. Monotonic time sources only move forward and are not affected by variations like timezones. An alternative to monotonic time is elapsed real time which is also known as wall-clock time. Elapsed real time is measured relative to another point in time.
Default time sources per platform
This table explains the default source of monotonic time for each platform:
Platform | Source |
---|---|
Kotlin/JVM | System.nanoTime() |
Kotlin/JS (Node.js) | process.hrtime() |
Kotlin/JS (browser) | window.performance.now() or Date.now() |
Kotlin/Native | std::chrono::high_resolution_clock or std::chrono::steady_clock |
Create time source
There are some cases where you might want to use a different time source. For example in Android, System.nanoTime()
only counts time while the device is active. It loses track of time when the device enters deep sleep. To keep track of
time while the device is in deep sleep, you can create a time source that uses SystemClock.elapsedRealtimeNanos()
):
object RealtimeMonotonicTimeSource : AbstractLongTimeSource(DurationUnit.NANOSECONDS) {
override fun read(): Long = SystemClock.elapsedRealtimeNanos()
}
Then you can use your time source to make time measurements:
fun main() {
val elapsed: Duration = RealtimeMonotonicTimeSource.measureTime {
Thread.sleep(100)
}
println(elapsed) // e.g. 103 ms
}
For more information about the kotlin.time
package, see our standard library API reference.