时间度量

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:

  1. import kotlin.time.*
  2. import kotlin.time.Duration.Companion.nanoseconds
  3. import kotlin.time.Duration.Companion.milliseconds
  4. import kotlin.time.Duration.Companion.seconds
  5. import kotlin.time.Duration.Companion.minutes
  6. import kotlin.time.Duration.Companion.days
  7. fun main() {
  8. //sampleStart
  9. val fiveHundredMilliseconds: Duration = 500.milliseconds
  10. val zeroSeconds: Duration = 0.seconds
  11. val tenMinutes: Duration = 10.minutes
  12. val negativeNanosecond: Duration = (-1).nanoseconds
  13. val infiniteDays: Duration = Double.POSITIVE_INFINITY.days
  14. val negativeInfiniteDays: Duration = Double.NEGATIVE_INFINITY.days
  15. println(fiveHundredMilliseconds) // 500ms
  16. println(zeroSeconds) // 0s
  17. println(tenMinutes) // 10m
  18. println(negativeNanosecond) // -1ns
  19. println(infiniteDays) // Infinity
  20. println(negativeInfiniteDays) // -Infinity
  21. //sampleEnd
  22. }

You can also perform basic arithmetic with Duration objects:

  1. import kotlin.time.*
  2. import kotlin.time.Duration.Companion.seconds
  3. fun main() {
  4. //sampleStart
  5. val fiveSeconds: Duration = 5.seconds
  6. val thirtySeconds: Duration = 30.seconds
  7. println(fiveSeconds + thirtySeconds)
  8. // 35s
  9. println(thirtySeconds - fiveSeconds)
  10. // 25s
  11. println(fiveSeconds * 2)
  12. // 10s
  13. println(thirtySeconds / 2)
  14. // 15s
  15. println(thirtySeconds / fiveSeconds)
  16. // 6.0
  17. println(-thirtySeconds)
  18. // -30s
  19. println((-thirtySeconds).absoluteValue)
  20. // 30s
  21. //sampleEnd
  22. }

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:

  1. import kotlin.time.Duration
  2. import kotlin.time.Duration.Companion.milliseconds
  3. import kotlin.time.DurationUnit
  4. fun main() {
  5. //sampleStart
  6. // Print in seconds with 2 decimal places
  7. println(5887.milliseconds.toString(DurationUnit.SECONDS, 2))
  8. // 5.89s
  9. //sampleEnd
  10. }

To get an ISO-8601-compatible string, use the toIsoString() function:

  1. import kotlin.time.Duration.Companion.seconds
  2. fun main() {
  3. //sampleStart
  4. println(86420.seconds.toIsoString()) // PT24H0M20S
  5. //sampleEnd
  6. }

Convert duration

To convert your Duration into a different DurationUnit, use the following properties:

  • inWholeNanoseconds
  • inWholeMicroseconds
  • inWholeSeconds
  • inWholeMinutes
  • inWholeHours
  • inWholeDays

For example:

  1. import kotlin.time.Duration
  2. import kotlin.time.Duration.Companion.minutes
  3. fun main() {
  4. //sampleStart
  5. val thirtyMinutes: Duration = 30.minutes
  6. println(thirtyMinutes.inWholeSeconds)
  7. // 1800
  8. //sampleEnd
  9. }

Alternatively, you can use your desired DurationUnit as a function parameter in the following extension functions:

  • .toInt()
  • .toDouble()
  • .toLong()

For example:

  1. import kotlin.time.Duration.Companion.seconds
  2. import kotlin.time.DurationUnit
  3. fun main() {
  4. //sampleStart
  5. println(270.seconds.toDouble(DurationUnit.MINUTES))
  6. // 4.5
  7. //sampleEnd
  8. }

Compare duration

To check if Duration objects are equal, use the equality operator (==):

  1. import kotlin.time.Duration
  2. import kotlin.time.Duration.Companion.hours
  3. import kotlin.time.Duration.Companion.minutes
  4. fun main() {
  5. //sampleStart
  6. val thirtyMinutes: Duration = 30.minutes
  7. val halfHour: Duration = 0.5.hours
  8. println(thirtyMinutes == halfHour)
  9. // true
  10. //sampleEnd
  11. }

To compare Duration objects, use the comparison operators (<, >):

  1. import kotlin.time.Duration.Companion.microseconds
  2. import kotlin.time.Duration.Companion.nanoseconds
  3. fun main() {
  4. //sampleStart
  5. println(3000.microseconds < 25000.nanoseconds)
  6. // false
  7. //sampleEnd
  8. }

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:

  1. import kotlin.time.Duration
  2. import kotlin.time.Duration.Companion.minutes
  3. fun main() {
  4. //sampleStart
  5. val thirtyMinutes: Duration = 30.minutes
  6. println(thirtyMinutes.toComponents { hours, minutes, _, _ -> "${hours}h:${minutes}m" })
  7. // 0h:30m
  8. //sampleEnd
  9. }

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:

  1. import kotlin.time.measureTime
  2. fun main() {
  3. //sampleStart
  4. val timeTaken = measureTime {
  5. Thread.sleep(100)
  6. }
  7. println(timeTaken) // e.g. 103 ms
  8. //sampleEnd
  9. }

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:

  1. import kotlin.time.measureTimedValue
  2. fun main() {
  3. //sampleStart
  4. val (value, timeTaken) = measureTimedValue {
  5. Thread.sleep(100)
  6. 42
  7. }
  8. println(value) // 42
  9. println(timeTaken) // e.g. 103 ms
  10. //sampleEnd
  11. }

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:

  1. import kotlin.time.*
  2. fun main() {
  3. val timeSource = TimeSource.Monotonic
  4. val mark = timeSource.markNow()
  5. }

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:

  1. import kotlin.time.*
  2. fun main() {
  3. //sampleStart
  4. val timeSource = TimeSource.Monotonic
  5. val mark1 = timeSource.markNow()
  6. Thread.sleep(500) // Sleep 0.5 seconds.
  7. val mark2 = timeSource.markNow()
  8. repeat(4) { n ->
  9. val mark3 = timeSource.markNow()
  10. val elapsed1 = mark3 - mark1
  11. val elapsed2 = mark3 - mark2
  12. println("Measurement 1.${n + 1}: elapsed1=$elapsed1, elapsed2=$elapsed2, diff=${elapsed1 - elapsed2}")
  13. }
  14. println(mark2 > mark1) // This is true, as mark2 was captured later than mark1.
  15. // true
  16. //sampleEnd
  17. }

To check if a deadline has passed or a timeout has been reached, use the hasPassedNow() and hasNotPassedNow() extension functions:

  1. import kotlin.time.*
  2. import kotlin.time.Duration.Companion.seconds
  3. fun main() {
  4. //sampleStart
  5. val timeSource = TimeSource.Monotonic
  6. val mark1 = timeSource.markNow()
  7. val fiveSeconds: Duration = 5.seconds
  8. val mark2 = mark1 + fiveSeconds
  9. // It hasn't been 5 seconds yet
  10. println(mark2.hasPassedNow())
  11. // false
  12. // Wait six seconds
  13. Thread.sleep(6000)
  14. println(mark2.hasPassedNow())
  15. // true
  16. //sampleEnd
  17. }

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:

PlatformSource
Kotlin/JVMSystem.nanoTime()
Kotlin/JS (Node.js)process.hrtime()
Kotlin/JS (browser)window.performance.now() or Date.now()
Kotlin/Nativestd::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()):

  1. object RealtimeMonotonicTimeSource : AbstractLongTimeSource(DurationUnit.NANOSECONDS) {
  2. override fun read(): Long = SystemClock.elapsedRealtimeNanos()
  3. }

Then you can use your time source to make time measurements:

  1. fun main() {
  2. val elapsed: Duration = RealtimeMonotonicTimeSource.measureTime {
  3. Thread.sleep(100)
  4. }
  5. println(elapsed) // e.g. 103 ms
  6. }

For more information about the kotlin.time package, see our standard library API reference.