Spec-Zone.ru › Kotlin 1.9

Измерение времени

Стандартная библиотека Kotlin предоставляет инструменты для расчета и измерения времени в различных единицах. Точное измерение времени важно для таких задач, как:

  • Управление потоками или процессами

  • Сбор статистики

  • Обнаружение таймаутов

  • Отладка

По умолчанию, время измеряется с помощью монотонного источника времени, но можно настроить и другие источники времени. Для получения дополнительной информации см. Настройка источника времени.

Вычисление продолжительности

Для представления промежутка времени стандартная библиотека предоставляет класс Duration. Продолжительность может быть выражена в следующих единицах из перечисления DurationUnit:

  • NANOSECONDS

  • MICROSECONDS

  • MILLISECONDS

  • SECONDS

  • MINUTES

  • HOURS

  • DAYS

Продолжительность может быть положительной, отрицательной, нулевой, положительной бесконечностью или отрицательной бесконечностью.

Создание продолжительности

Для создания продолжительности используйте расширяющие свойства, доступные для типов Int, Long, и Double: nanoseconds, microseconds, milliseconds, seconds, minutes, hours, и days.

Дни относятся к периодам продолжительностью 24 часа. Это не календарные дни.

Например:

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
}

Вы также можете выполнять основные арифметические операции с объектами Duration:

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
}

Получение строкового представления

Полезно иметь строковое представление продолжительности для вывода, сериализации, передачи или хранения.

Для получения строкового представления используйте функцию .toString(). По умолчанию, время отображается с использованием каждой присутствующей единицы. Например: 1h 0m 45.677s или -(6d 5h 5m 28.284s).

Для настройки вывода используйте функцию .toString() с желаемыми параметрами DurationUnit и количеством десятичных знаков.

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
}

Для получения строки в формате ISO-8601 используйте функцию toIsoString():

import kotlin.time.Duration.Companion.seconds

fun main() {
//sampleStart
    println(86420.seconds.toIsoString()) // PT24H0M20S
//sampleEnd
}

Преобразование продолжительности

Для преобразования продолжительности в другие единицы используйте следующие свойства:

  • inWholeNanoseconds

  • inWholeMicroseconds

  • inWholeSeconds

  • inWholeMinutes

  • inWholeHours

  • inWholeDays

Например:

import kotlin.time.Duration
import kotlin.time.Duration.Companion.minutes

fun main() {
//sampleStart
    val thirtyMinutes: Duration = 30.minutes
    println(thirtyMinutes.inWholeSeconds)
    // 1800
//sampleEnd
}

Также вы можете использовать желаемую единицу в качестве параметра в следующих расширяющих функциях:

  • .toInt()

  • .toDouble()

  • .toLong()

Например:

import kotlin.time.Duration.Companion.seconds
import kotlin.time.DurationUnit

fun main() {
//sampleStart
    println(270.seconds.toDouble(DurationUnit.MINUTES))
    // 4.5
//sampleEnd
}

Сравнение продолжительностей

Для проверки равенства объектов Duration используйте оператор равенства (==):

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
}

Для сравнения объектов Duration используйте операторы сравнения (<, >):

import kotlin.time.Duration.Companion.microseconds
import kotlin.time.Duration.Companion.nanoseconds

fun main() {
//sampleStart
    println(3000.microseconds < 25000.nanoseconds)
    // false
//sampleEnd
}

Разбиение продолжительности на компоненты

Для разбиения продолжительности на компоненты времени и последующего выполнения действия используйте перегрузку функции toComponents(). Добавьте необходимое действие в виде функции или лямбда-выражения в качестве параметра.

Например:

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
}

В этом примере лямбда-выражение имеет hours и minutes в качестве параметров с нижними подчеркиваниями (_) для неиспользуемых параметров seconds и nanoseconds. Выражение возвращает объединенную строку, используя шаблоны строк, для получения желаемого формата вывода hours и minutes.

Измерение времени

Для отслеживания хода времени стандартная библиотека предоставляет инструменты для:

  • Измерения времени выполнения кода в заданной единице времени.

  • Пометки момента времени.

  • Сравнения и вычитания двух моментов времени.

  • Определения прошедшего времени с момента определенного момента.

  • Проверки, является ли текущее время позже определенного момента.

Измерение времени выполнения кода

Для измерения времени выполнения блока кода используйте встроенную функцию measureTime:

import kotlin.time.measureTime

fun main() {
//sampleStart
    val timeTaken = measureTime {
        Thread.sleep(100)
    }
    println(timeTaken) // e.g. 103 ms
//sampleEnd
}

Для измерения времени выполнения блока кода и возврата значения блока кода используйте встроенную функцию measureTimedValue.

Например:

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
}

По умолчанию обе функции используют монотонный источник времени.

Пометка моментов времени

Для пометки конкретного момента времени используйте интерфейс TimeSource и функцию markNow() для создания объекта TimeMark:

import kotlin.time.*

fun main() {
   val timeSource = TimeSource.Monotonic
   val mark = timeSource.markNow()
}

Измерение разницы во времени

Для измерения разницы между объектами TimeMark из одного источника времени используйте оператор вычитания (-).

Для сравнения объектов TimeMark из одного источника времени используйте операторы сравнения (<, >).

Например:

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
}

Для проверки достижения дедлайна или таймаута используйте расширяющие функции hasPassedNow() и hasNotPassedNow():

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
}

Источники времени

По умолчанию время измеряется с помощью монотонного источника времени. Монотонные источники времени движутся только вперед и не зависят от таких факторов, как часовые пояса. Альтернативой монотонному времени является реальное прошедшее время, также известное как время по часам. Реальное прошедшее время измеряется относительно другой точки во времени.

Источники времени по умолчанию для каждой платформы

В этой таблице показан стандартный источник монотонного времени для каждой платформы:

Платформа

Источник

Kotlin/JVM

System.nanoTime()

Kotlin/JS (Node.js)

process.hrtime()

Kotlin/JS (браузер)

window.performance.now() или Date.now()

Kotlin/Native

std::chrono::high_resolution_clock или std::chrono::steady_clock

Создание источника времени

В некоторых случаях вам может потребоваться использовать другой источник времени. Например, в Android, System.nanoTime() считает время только пока устройство активное. Оно теряет отслеживание времени, когда устройство переходит в глубокий сон. Чтобы отслеживать время, когда устройство находится в глубоком сне, вы можете создать источник времени, который использует SystemClock.elapsedRealtimeNanos():

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

Затем вы можете использовать свой источник времени для измерения времени:

fun main() {
    val elapsed: Duration = RealtimeMonotonicTimeSource.measureTime {
        Thread.sleep(100)
    }
    println(elapsed) // e.g. 103 ms
}

Для получения дополнительной информации о пакете kotlin.time, см. нашу ссылку на API стандартной библиотеки.

Последнее изменение: 24 июля 2023 г.
Функции области видимости Руководство по сопрограммам

© 2010–2023 JetBrains s.r.o. and Kotlin Programming Language contributors
Licensed under the Apache License, Version 2.0.
https://kotlinlang.org/docs/time-measurement.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API