Stabilize Duration, DurationUnit and related top-level functions KT-46784

Co-authored-by: Abduqodiri Qurbonzoda <abduqodiri.qurbonzoda@jetbrains.com>
This commit is contained in:
Ilya Gorbunov
2021-09-19 04:36:44 +03:00
committed by Space
parent ad18343413
commit 96611de344
12 changed files with 60 additions and 117 deletions
+17 -29
View File
@@ -26,8 +26,8 @@ import kotlin.math.*
* use the functions [toInt], [toLong], and [toDouble]
* or the properties [inWholeHours], [inWholeMinutes], [inWholeSeconds], [inWholeNanoseconds], and so on.
*/
@SinceKotlin("1.3")
@ExperimentalTime
@SinceKotlin("1.6")
@WasExperimental(ExperimentalTime::class)
@JvmInline
public value class Duration internal constructor(private val rawValue: Long) : Comparable<Duration> {
@@ -183,7 +183,6 @@ public value class Duration internal constructor(private val rawValue: Long) : C
* @throws IllegalArgumentException if the string doesn't represent a duration in any of the supported formats.
* @sample samples.time.Durations.parse
*/
@SinceKotlin("1.5")
public fun parse(value: String): Duration = try {
parseDuration(value, strictIso = false)
} catch (e: IllegalArgumentException) {
@@ -196,7 +195,6 @@ public value class Duration internal constructor(private val rawValue: Long) : C
* @throws IllegalArgumentException if the string doesn't represent a duration in ISO-8601 format.
* @sample samples.time.Durations.parseIsoString
*/
@SinceKotlin("1.5")
public fun parseIsoString(value: String): Duration = try {
parseDuration(value, strictIso = true)
} catch (e: IllegalArgumentException) {
@@ -214,7 +212,6 @@ public value class Duration internal constructor(private val rawValue: Long) : C
* e.g. `10s`, `1h 30m` or `-(1h 30m)`.
* @sample samples.time.Durations.parse
*/
@SinceKotlin("1.5")
public fun parseOrNull(value: String): Duration? = try {
parseDuration(value, strictIso = false)
} catch (e: IllegalArgumentException) {
@@ -226,7 +223,6 @@ public value class Duration internal constructor(private val rawValue: Long) : C
* or `null` if the string doesn't represent a duration in ISO-8601 format.
* @sample samples.time.Durations.parseIsoString
*/
@SinceKotlin("1.5")
public fun parseIsoStringOrNull(value: String): Duration? = try {
parseDuration(value, strictIso = true)
} catch (e: IllegalArgumentException) {
@@ -603,7 +599,6 @@ public value class Duration internal constructor(private val rawValue: Long) : C
*
* An infinite duration value is converted either to [Long.MAX_VALUE] or [Long.MIN_VALUE] depending on its sign.
*/
@SinceKotlin("1.5")
public val inWholeDays: Long
get() = toLong(DurationUnit.DAYS)
@@ -612,7 +607,6 @@ public value class Duration internal constructor(private val rawValue: Long) : C
*
* An infinite duration value is converted either to [Long.MAX_VALUE] or [Long.MIN_VALUE] depending on its sign.
*/
@SinceKotlin("1.5")
public val inWholeHours: Long
get() = toLong(DurationUnit.HOURS)
@@ -621,7 +615,6 @@ public value class Duration internal constructor(private val rawValue: Long) : C
*
* An infinite duration value is converted either to [Long.MAX_VALUE] or [Long.MIN_VALUE] depending on its sign.
*/
@SinceKotlin("1.5")
public val inWholeMinutes: Long
get() = toLong(DurationUnit.MINUTES)
@@ -630,7 +623,6 @@ public value class Duration internal constructor(private val rawValue: Long) : C
*
* An infinite duration value is converted either to [Long.MAX_VALUE] or [Long.MIN_VALUE] depending on its sign.
*/
@SinceKotlin("1.5")
public val inWholeSeconds: Long
get() = toLong(DurationUnit.SECONDS)
@@ -639,7 +631,6 @@ public value class Duration internal constructor(private val rawValue: Long) : C
*
* An infinite duration value is converted either to [Long.MAX_VALUE] or [Long.MIN_VALUE] depending on its sign.
*/
@SinceKotlin("1.5")
public val inWholeMilliseconds: Long
get() {
return if (isInMillis() && isFinite()) value else toLong(DurationUnit.MILLISECONDS)
@@ -654,7 +645,6 @@ public value class Duration internal constructor(private val rawValue: Long) : C
*
* An infinite duration value is converted either to [Long.MAX_VALUE] or [Long.MIN_VALUE] depending on its sign.
*/
@SinceKotlin("1.5")
public val inWholeMicroseconds: Long
get() = toLong(DurationUnit.MICROSECONDS)
@@ -667,7 +657,6 @@ public value class Duration internal constructor(private val rawValue: Long) : C
*
* An infinite duration value is converted either to [Long.MAX_VALUE] or [Long.MIN_VALUE] depending on its sign.
*/
@SinceKotlin("1.5")
public val inWholeNanoseconds: Long
get() {
val value = value
@@ -851,8 +840,8 @@ public value class Duration internal constructor(private val rawValue: Long) : C
// extension functions
/** Returns a [Duration] equal to this [Int] number of the specified [unit]. */
@SinceKotlin("1.3")
@ExperimentalTime
@SinceKotlin("1.6")
@WasExperimental(ExperimentalTime::class)
public fun Int.toDuration(unit: DurationUnit): Duration {
return if (unit <= DurationUnit.SECONDS) {
durationOfNanos(convertDurationUnitOverflow(this.toLong(), unit, DurationUnit.NANOSECONDS))
@@ -861,8 +850,8 @@ public fun Int.toDuration(unit: DurationUnit): Duration {
}
/** Returns a [Duration] equal to this [Long] number of the specified [unit]. */
@SinceKotlin("1.3")
@ExperimentalTime
@SinceKotlin("1.6")
@WasExperimental(ExperimentalTime::class)
public fun Long.toDuration(unit: DurationUnit): Duration {
val maxNsInUnit = convertDurationUnitOverflow(MAX_NANOS, DurationUnit.NANOSECONDS, unit)
if (this in -maxNsInUnit..maxNsInUnit) {
@@ -878,8 +867,8 @@ public fun Long.toDuration(unit: DurationUnit): Duration {
*
* @throws IllegalArgumentException if this `Double` value is `NaN`.
*/
@SinceKotlin("1.3")
@ExperimentalTime
@SinceKotlin("1.6")
@WasExperimental(ExperimentalTime::class)
public fun Double.toDuration(unit: DurationUnit): Duration {
val valueInNs = convertDurationUnit(this, unit, DurationUnit.NANOSECONDS)
require(!valueInNs.isNaN()) { "Duration value cannot be NaN." }
@@ -1051,8 +1040,8 @@ public val Double.days get() = toDuration(DurationUnit.DAYS)
/** Returns a duration whose value is the specified [duration] value multiplied by this number. */
@SinceKotlin("1.3")
@ExperimentalTime
@SinceKotlin("1.6")
@WasExperimental(ExperimentalTime::class)
@kotlin.internal.InlineOnly
public inline operator fun Int.times(duration: Duration): Duration = duration * this
@@ -1061,14 +1050,13 @@ public inline operator fun Int.times(duration: Duration): Duration = duration *
*
* @throws IllegalArgumentException if the operation results in a `NaN` value.
*/
@SinceKotlin("1.3")
@ExperimentalTime
@SinceKotlin("1.6")
@WasExperimental(ExperimentalTime::class)
@kotlin.internal.InlineOnly
public inline operator fun Double.times(duration: Duration): Duration = duration * this
@ExperimentalTime
private fun parseDuration(value: String, strictIso: Boolean): Duration {
var length = value.length
if (length == 0) throw IllegalArgumentException("The string is empty")
@@ -1197,17 +1185,17 @@ private const val MAX_NANOS_IN_MILLIS = MAX_NANOS / NANOS_IN_MILLIS
private fun nanosToMillis(nanos: Long): Long = nanos / NANOS_IN_MILLIS
private fun millisToNanos(millis: Long): Long = millis * NANOS_IN_MILLIS
@ExperimentalTime private fun durationOfNanos(normalNanos: Long) = Duration(normalNanos shl 1)
@ExperimentalTime private fun durationOfMillis(normalMillis: Long) = Duration((normalMillis shl 1) + 1)
@ExperimentalTime private fun durationOf(normalValue: Long, unitDiscriminator: Int) = Duration((normalValue shl 1) + unitDiscriminator)
@ExperimentalTime private fun durationOfNanosNormalized(nanos: Long) =
private fun durationOfNanos(normalNanos: Long) = Duration(normalNanos shl 1)
private fun durationOfMillis(normalMillis: Long) = Duration((normalMillis shl 1) + 1)
private fun durationOf(normalValue: Long, unitDiscriminator: Int) = Duration((normalValue shl 1) + unitDiscriminator)
private fun durationOfNanosNormalized(nanos: Long) =
if (nanos in -MAX_NANOS..MAX_NANOS) {
durationOfNanos(nanos)
} else {
durationOfMillis(nanosToMillis(nanos))
}
@ExperimentalTime private fun durationOfMillisNormalized(millis: Long) =
private fun durationOfMillisNormalized(millis: Long) =
if (millis in -MAX_NANOS_IN_MILLIS..MAX_NANOS_IN_MILLIS) {
durationOfNanos(millisToNanos(millis))
} else {
@@ -14,8 +14,8 @@ package kotlin.time
*
* The smallest time unit is [NANOSECONDS] and the largest is [DAYS], which corresponds to exactly 24 [HOURS].
*/
@SinceKotlin("1.3")
@ExperimentalTime
@SinceKotlin("1.6")
@WasExperimental(ExperimentalTime::class)
public expect enum class DurationUnit {
/**
* Time unit representing one nanosecond, which is 1/1000 of a microsecond.
@@ -49,22 +49,18 @@ public expect enum class DurationUnit {
/** Converts the given time duration [value] expressed in the specified [sourceUnit] into the specified [targetUnit]. */
@SinceKotlin("1.3")
@ExperimentalTime
internal expect fun convertDurationUnit(value: Double, sourceUnit: DurationUnit, targetUnit: DurationUnit): Double
// overflown result is unspecified
@SinceKotlin("1.5")
@ExperimentalTime
internal expect fun convertDurationUnitOverflow(value: Long, sourceUnit: DurationUnit, targetUnit: DurationUnit): Long
// overflown result is coerced in the Long range boundaries
@SinceKotlin("1.5")
@ExperimentalTime
internal expect fun convertDurationUnit(value: Long, sourceUnit: DurationUnit, targetUnit: DurationUnit): Long
@SinceKotlin("1.3")
@ExperimentalTime
@Suppress("REDUNDANT_ELSE_IN_WHEN")
internal fun DurationUnit.shortName(): String = when (this) {
DurationUnit.NANOSECONDS -> "ns"
@@ -78,7 +74,6 @@ internal fun DurationUnit.shortName(): String = when (this) {
}
@SinceKotlin("1.5")
@ExperimentalTime
internal fun durationUnitByShortName(shortName: String): DurationUnit = when (shortName) {
"ns" -> DurationUnit.NANOSECONDS
"us" -> DurationUnit.MICROSECONDS
@@ -91,7 +86,6 @@ internal fun durationUnitByShortName(shortName: String): DurationUnit = when (sh
}
@SinceKotlin("1.5")
@ExperimentalTime
internal fun durationUnitByIsoChar(isoChar: Char, isTimeComponent: Boolean): DurationUnit =
when {
!isTimeComponent -> {