jdk8Main.time.Time.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of kotlinx-coroutines-core-jvm Show documentation
Show all versions of kotlinx-coroutines-core-jvm Show documentation
Coroutines support libraries for Kotlin
The newest version!
@file:OptIn(ExperimentalContracts::class)
package kotlinx.coroutines.time
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
import kotlinx.coroutines.selects.*
import java.time.*
import java.time.temporal.*
import kotlin.contracts.*
/**
* "java.time" adapter method for [kotlinx.coroutines.delay].
*/
public suspend fun delay(duration: Duration): Unit = delay(duration.coerceToMillis())
/**
* "java.time" adapter method for [kotlinx.coroutines.flow.debounce].
*/
@FlowPreview
public fun Flow.debounce(timeout: Duration): Flow = debounce(timeout.coerceToMillis())
/**
* "java.time" adapter method for [kotlinx.coroutines.flow.sample].
*/
@FlowPreview
public fun Flow.sample(period: Duration): Flow = sample(period.coerceToMillis())
/**
* "java.time" adapter method for [SelectBuilder.onTimeout].
*/
public fun SelectBuilder.onTimeout(duration: Duration, block: suspend () -> R): Unit =
onTimeout(duration.coerceToMillis(), block)
/**
* "java.time" adapter method for [kotlinx.coroutines.withTimeout].
*/
public suspend fun withTimeout(duration: Duration, block: suspend CoroutineScope.() -> T): T {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
return kotlinx.coroutines.withTimeout(duration.coerceToMillis(), block)
}
/**
* "java.time" adapter method for [kotlinx.coroutines.withTimeoutOrNull].
*/
public suspend fun withTimeoutOrNull(duration: Duration, block: suspend CoroutineScope.() -> T): T? =
kotlinx.coroutines.withTimeoutOrNull(duration.coerceToMillis(), block)
/**
* Coerces the given [Duration] to a millisecond delay.
* Negative values are coerced to zero, values that cannot
* be represented in milliseconds as long ("infinite" duration) are coerced to [Long.MAX_VALUE]
* and durations lesser than a millisecond are coerced to 1 millisecond.
*
* The rationale of coercion:
* 1) Too large durations typically indicate infinity and Long.MAX_VALUE is the
* best approximation of infinity we can provide.
* 2) Coercing too small durations to 1 instead of 0 is crucial for two patterns:
* - Programming with deadlines and delays
* - Non-suspending fast-paths (e.g. `withTimeout(1 nanosecond) { 42 }` should not throw)
*/
private fun Duration.coerceToMillis(): Long {
if (this <= Duration.ZERO) return 0
if (this <= ChronoUnit.MILLIS.duration) return 1
// Maximum scalar values of Duration.ofMillis(Long.MAX_VALUE)
val maxSeconds = 9223372036854775
val maxNanos = 807000000
return if (seconds < maxSeconds || seconds == maxSeconds && nano < maxNanos) toMillis()
else Long.MAX_VALUE
}