Add remaining docs for Duration members, runnable samples for toString

This commit is contained in:
Ilya Gorbunov
2019-06-06 13:59:00 +03:00
parent ffd9d8c71d
commit 58b04c7974
6 changed files with 250 additions and 10 deletions
+4
View File
@@ -145,6 +145,10 @@ Functions for writing test assertions.
Functions for working with text and regular expressions.
# Package kotlin.time
Experimental API for representing [Duration][kotlin.time.Duration] values and measuring time intervals.
# Package org.khronos.webgl
Kotlin JavaScript wrappers for the WebGL API.
@@ -18,6 +18,9 @@ package kotlin.time
public interface Clock {
/**
* Marks a time point on this clock.
*
* The returned [ClockMark] instance encapsulates captured time point and allows querying
* the duration of time interval [elapsed][ClockMark.elapsed] from that point.
*/
public fun mark(): ClockMark
}
+22 -2
View File
@@ -8,7 +8,10 @@ package kotlin.time
import kotlin.js.JsName
/**
* The most precise clock available in the platform, whose readings increase monotonically over time.
* The most precise clock available in the platform.
*
* The clock returns its readings from a source of monotonic time when it is available in a target platform,
* and resorts to a non-monotonic time source otherwise.
*/
@SinceKotlin("1.3")
@ExperimentalTime
@@ -16,10 +19,16 @@ public expect object MonoClock : Clock
/**
* An abstract class used to implement clocks that return their readings as [Long] values in the specified [unit].
*
* @property unit The unit in which this clock readings are expressed.
*/
@SinceKotlin("1.3")
@ExperimentalTime
public abstract class AbstractLongClock(protected val unit: DurationUnit) : Clock {
/**
* This protected method should be overridden to return the current reading of the clock expressed as a [Long] number
* in the unit specified by the [unit] property.
*/
protected abstract fun read(): Long
private class LongClockMark(val startedAt: Long, val clock: AbstractLongClock, val offset: Duration) : ClockMark() {
@@ -32,10 +41,16 @@ public abstract class AbstractLongClock(protected val unit: DurationUnit) : Cloc
/**
* An abstract class used to implement clocks that return their readings as [Double] values in the specified [unit].
*
* @property unit The unit in which this clock readings are expressed.
*/
@SinceKotlin("1.3")
@ExperimentalTime
public abstract class AbstractDoubleClock(protected val unit: DurationUnit) : Clock {
/**
* This protected method should be overridden to return the current reading of the clock expressed as a [Double] number
* in the unit specified by the [unit] property.
*/
protected abstract fun read(): Double
private class DoubleClockMark(val startedAt: Double, val clock: AbstractDoubleClock, val offset: Duration) : ClockMark() {
@@ -47,7 +62,12 @@ public abstract class AbstractDoubleClock(protected val unit: DurationUnit) : Cl
}
/**
* A clock, whose readings can be preset and changed manually. It is useful as a predictable source of time in tests.
* A clock that has programmatically updatable readings. It is useful as a predictable source of time in tests.
*
* @param reading The initial value of the clock reading.
* @param unit The unit of time in which [reading] value is expressed.
*
* @property reading Gets or sets this clock's current reading value.
*/
@SinceKotlin("1.3")
@ExperimentalTime
+172 -7
View File
@@ -17,12 +17,12 @@ private val storageUnit = DurationUnit.NANOSECONDS
* An infinite duration value [Duration.INFINITE] can be used to represent infinite timeouts.
*
* To construct a duration use either the extension function [toDuration],
* or the extension properties [hours], [minutes], [seconds] and so on,
* available on [Int], [Long] and [Double] numeric types.
* or the extension properties [hours], [minutes], [seconds], and so on,
* available on [Int], [Long], and [Double] numeric types.
*
* To get the value of this duration expressed in a particular [duration units][DurationUnit]
* use the functions [toInt], [toLong] and [toDouble]
* or the properties [inHours], [inMinutes], [inSeconds], [inNanoseconds] and so on.
* use the functions [toInt], [toLong], and [toDouble]
* or the properties [inHours], [inMinutes], [inSeconds], [inNanoseconds], and so on.
*/
@SinceKotlin("1.3")
@ExperimentalTime
@@ -35,7 +35,10 @@ public inline class Duration internal constructor(internal val value: Double) :
// }
companion object {
/** The duration equal to exactly 0 seconds. */
public val ZERO: Duration = Duration(0.0)
/** The duration whose value is positive infinity. It is useful for representing timeouts that should never expire. */
public val INFINITE: Duration = Duration(Double.POSITIVE_INFINITY)
/** Converts the given time duration [value] expressed in the specified [sourceUnit] into the specified [targetUnit]. */
@@ -45,41 +48,100 @@ public inline class Duration internal constructor(internal val value: Double) :
// arithmetic operators
/** Returns the negative of this value. */
public operator fun unaryMinus(): Duration = Duration(-value)
/** Returns a duration whose value is the sum of this and [other] duration values. */
public operator fun plus(other: Duration): Duration = Duration(value + other.value)
/** Returns a duration whose value is the difference between this and [other] duration values. */
public operator fun minus(other: Duration): Duration = Duration(value - other.value)
// should we declare symmetric extension operators?
/** Returns a duration whose value is this duration value multiplied by the given [scale] number. */
public operator fun times(scale: Int): Duration = Duration(value * scale)
/** Returns a duration whose value is this duration value multiplied by the given [scale] number. */
public operator fun times(scale: Double): Duration = Duration(value * scale)
/** Returns a duration whose value is this duration value divided by the given [scale] number. */
public operator fun div(scale: Int): Duration = Duration(value / scale)
/** Returns a duration whose value is this duration value divided by the given [scale] number. */
public operator fun div(scale: Double): Duration = Duration(value / scale)
/** Returns a number that is the ratio of [this] and [other] duration values. */
public operator fun div(other: Duration): Double = this.value / other.value
/** Returns true, if the duration value is less than zero. */
public fun isNegative(): Boolean = value < 0
/** Returns true, if the duration value is infinite. */
public fun isInfinite(): Boolean = value.isInfinite()
/** Returns true, if the duration value is finite. */
public fun isFinite(): Boolean = value.isFinite()
/** Returns the absolute value of this value. The returned value is always non-negative. */
public val absoluteValue: Duration get() = if (isNegative()) -this else this
override fun compareTo(other: Duration): Int = this.value.compareTo(other.value)
// splitting to components
/**
* Splits this duration into days, hours, minutes, seconds, and nanoseconds and executes the given [action] with these components.
* The result of [action] is returned as the result of this function.
*
* - `nanoseconds` represents the whole number of nanoseconds in this duration, and its absolute value is less than 1_000_000_000;
* - `seconds` represents the whole number of seconds in this duration, and its absolute value is less than 60;
* - `minutes` represents the whole number of minutes in this duration, and its absolute value is less than 60;
* - `hours` represents the whole number of hours in this duration, and its absolute value is less than 24;
* - `days` represents the whole number of days in this duration.
* If the value doesn't fit in [Int] range, i.e. it's greater than [Int.MAX_VALUE] or less than [Int.MIN_VALUE],
* it is coerced into that range.
*/
public inline fun <T> toComponents(action: (days: Int, hours: Int, minutes: Int, seconds: Int, nanoseconds: Int) -> T): T =
action(inDays.toInt(), hoursComponent, minutesComponent, secondsComponent, nanosecondsComponent)
/**
* Splits this duration into hours, minutes, seconds, and nanoseconds and executes the given [action] with these components.
* The result of [action] is returned as the result of this function.
*
* - `nanoseconds` represents the whole number of nanoseconds in this duration, and its absolute value is less than 1_000_000_000;
* - `seconds` represents the whole number of seconds in this duration, and its absolute value is less than 60;
* - `minutes` represents the whole number of minutes in this duration, and its absolute value is less than 60;
* - `hours` represents the whole number of hours in this duration.
* If the value doesn't fit in [Int] range, i.e. it's greater than [Int.MAX_VALUE] or less than [Int.MIN_VALUE],
* it is coerced into that range.
*/
public inline fun <T> toComponents(action: (hours: Int, minutes: Int, seconds: Int, nanoseconds: Int) -> T): T =
action(inHours.toInt(), minutesComponent, secondsComponent, nanosecondsComponent)
/**
* Splits this duration into minutes, seconds, and nanoseconds and executes the given [action] with these components.
* The result of [action] is returned as the result of this function.
*
* - `nanoseconds` represents the whole number of nanoseconds in this duration, and its absolute value is less than 1_000_000_000;
* - `seconds` represents the whole number of seconds in this duration, and its absolute value is less than 60;
* - `minutes` represents the whole number of minutes in this duration.
* If the value doesn't fit in [Int] range, i.e. it's greater than [Int.MAX_VALUE] or less than [Int.MIN_VALUE],
* it is coerced into that range.
*/
public inline fun <T> toComponents(action: (minutes: Int, seconds: Int, nanoseconds: Int) -> T): T =
action(inMinutes.toInt(), secondsComponent, nanosecondsComponent)
/**
* Splits this duration into seconds, and nanoseconds and executes the given [action] with these components.
* The result of [action] is returned as the result of this function.
*
* - `nanoseconds` represents the whole number of nanoseconds in this duration, and its absolute value is less than 1_000_000_000;
* - `seconds` represents the whole number of seconds in this duration.
* If the value doesn't fit in [Long] range, i.e. it's greater than [Long.MAX_VALUE] or less than [Long.MIN_VALUE],
* it is coerced into that range.
*/
public inline fun <T> toComponents(action: (seconds: Long, nanoseconds: Int) -> T): T =
action(inSeconds.toLong(), nanosecondsComponent)
@@ -95,25 +157,77 @@ public inline class Duration internal constructor(internal val value: Double) :
// conversion to units
/** Returns the value of this duration expressed as a [Double] number of the specified [unit]. */
public fun toDouble(unit: DurationUnit): Double = convertDurationUnit(value, storageUnit, unit)
/**
* Returns the value of this duration expressed as a [Long] number of the specified [unit].
*
* If the value doesn't fit in the range of [Long] type, it is coerced into that range, see the conversion [Double.toLong] for details.
*/
public fun toLong(unit: DurationUnit): Long = toDouble(unit).toLong()
/**
* Returns the value of this duration expressed as an [Int] number of the specified [unit].
*
* If the value doesn't fit in the range of [Int] type, it is coerced into that range, see the conversion [Double.toInt] for details.
*/
public fun toInt(unit: DurationUnit): Int = toDouble(unit).toInt()
// option 1: in- properties
/** The value of this duration expressed as a [Double] number of days. */
public val inDays: Double get() = toDouble(DurationUnit.DAYS)
/** The value of this duration expressed as a [Double] number of hours. */
public val inHours: Double get() = toDouble(DurationUnit.HOURS)
/** The value of this duration expressed as a [Double] number of minutes. */
public val inMinutes: Double get() = toDouble(DurationUnit.MINUTES)
/** The value of this duration expressed as a [Double] number of seconds. */
public val inSeconds: Double get() = toDouble(DurationUnit.SECONDS)
/** The value of this duration expressed as a [Double] number of milliseconds. */
public val inMilliseconds: Double get() = toDouble(DurationUnit.MILLISECONDS)
/** The value of this duration expressed as a [Double] number of microseconds. */
public val inMicroseconds: Double get() = toDouble(DurationUnit.MICROSECONDS)
/** The value of this duration expressed as a [Double] number of nanoseconds. */
public val inNanoseconds: Double get() = toDouble(DurationUnit.NANOSECONDS)
// shortcuts
/**
* Returns the value of this duration expressed as a [Long] number of nanoseconds.
*
* If the value doesn't fit in the range of [Long] type, it is coerced into that range, see the conversion [Double.toLong] for details.
*
* The range of durations that can be expressed as a `Long` number of nanoseconds is approximately ±292 years.
*/
public fun toLongNanoseconds(): Long = toLong(DurationUnit.NANOSECONDS)
/**
* Returns the value of this duration expressed as a [Long] number of milliseconds.
*
* The value is coerced to the range of [Long] type, if it doesn't fit in that range, see the conversion [Double.toLong] for details.
*
* The range of durations that can be expressed as a `Long` number of milliseconds is approximately ±292 million years.
*/
public fun toLongMilliseconds(): Long = toLong(DurationUnit.MILLISECONDS)
/**
* Returns a string representation of this duration value expressed in the unit which yields the most compact and readable number value.
*
* Special cases:
* - zero duration is formatted as `"0s"`
* - the infinite duration is formatted as `"Infinity"` without unit
* - very small durations (less than 1e-15 s) are expressed in seconds and formatted in scientific notation
* - very big durations (more than 1e+7 days) are expressed in days and formatted in scientific notation
*
* @return the value of duration in the automatically determined unit followed by that unit abbreviated name: `d`, `h`, `m`, `s`, `ms`, `us`, or `ns`.
*
* @sample samples.time.Durations.toStringDefault
*/
override fun toString(): String = when {
isInfinite() -> value.toString()
value == 0.0 -> "0s"
@@ -149,6 +263,19 @@ public inline class Duration internal constructor(internal val value: Double) :
else -> 0
}
/**
* Returns a string representation of this duration value expressed in the given [unit]
* and formatted with the specified [decimals] number of digits after decimal point.
*
* Special cases:
* - the infinite duration is formatted as `"Infinity"` without unit
*
* @return the value of duration in the specified [unit] followed by that unit abbreviated name: `d`, `h`, `m`, `s`, `ms`, `us`, or `ns`.
*
* @throws IllegalArgumentException if [decimals] is less than zero.
*
* @sample samples.time.Durations.toStringDecimals
*/
public fun toString(unit: DurationUnit, decimals: Int = 0): String {
require(decimals >= 0) { "decimals must be not negative, but was $decimals" }
if (isInfinite()) return value.toString()
@@ -156,6 +283,20 @@ public inline class Duration internal constructor(internal val value: Double) :
}
/**
* Returns an ISO-8601 based string representation of this duration.
*
* The returned value is presented in the format `PThHmMs.fS`, where `h`, `m`, `s` are the integer components of this duration (see [toComponents])
* and `f` is a fractional part of second. Depending on the roundness of the value the fractional part can be formatted with either
* 0, 3, 6, or 9 decimal digits.
*
* If the hours component absolute value of this duration is greater than [Int.MAX_VAlUE], it is replaced with [Int.MAX_VALUE],
* so the infinite duration is formatted as `"PT2147483647H".
*
* Negative durations are indicated with the sign `-` in the beginning of the returned string, for example, `"-PT5M30S"`.
*
* @sample samples.time.Durations.toIsoString
*/
public fun toIsoString(): String = buildString {
if (isNegative()) append('-')
append("PT")
@@ -190,14 +331,17 @@ public inline class Duration internal constructor(internal val value: Double) :
// constructing from number of units
// extension functions
/** Returns a [Duration] equal to this [Int] number of the specified [unit]. */
@SinceKotlin("1.3")
@ExperimentalTime
public fun Int.toDuration(unit: DurationUnit): Duration = toDouble().toDuration(unit)
/** Returns a [Duration] equal to this [Long] number of the specified [unit]. */
@SinceKotlin("1.3")
@ExperimentalTime
public fun Long.toDuration(unit: DurationUnit): Duration = toDouble().toDuration(unit)
/** Returns a [Duration] equal to this [Double] number of the specified [unit]. */
@SinceKotlin("1.3")
@ExperimentalTime
public fun Double.toDuration(unit: DurationUnit): Duration = Duration(convertDurationUnit(this, unit, storageUnit))
@@ -205,86 +349,107 @@ public fun Double.toDuration(unit: DurationUnit): Duration = Duration(convertDur
// constructing from number of units
// extension properties
/** Returns a [Duration] equal to this [Int] number of nanoseconds. */
@SinceKotlin("1.3")
@ExperimentalTime
public val Int.nanoseconds get() = toDuration(DurationUnit.NANOSECONDS)
/** Returns a [Duration] equal to this [Long] number of nanoseconds. */
@SinceKotlin("1.3")
@ExperimentalTime
public val Long.nanoseconds get() = toDuration(DurationUnit.NANOSECONDS)
/** Returns a [Duration] equal to this [Double] number of nanoseconds. */
@SinceKotlin("1.3")
@ExperimentalTime
public val Double.nanoseconds get() = toDuration(DurationUnit.NANOSECONDS)
/** Returns a [Duration] equal to this [Int] number of microseconds. */
@SinceKotlin("1.3")
@ExperimentalTime
public val Int.microseconds get() = toDuration(DurationUnit.MICROSECONDS)
/** Returns a [Duration] equal to this [Long] number of microseconds. */
@SinceKotlin("1.3")
@ExperimentalTime
public val Long.microseconds get() = toDuration(DurationUnit.MICROSECONDS)
/** Returns a [Duration] equal to this [Double] number of microseconds. */
@SinceKotlin("1.3")
@ExperimentalTime
public val Double.microseconds get() = toDuration(DurationUnit.MICROSECONDS)
/** Returns a [Duration] equal to this [Int] number of milliseconds. */
@SinceKotlin("1.3")
@ExperimentalTime
public val Int.milliseconds get() = toDuration(DurationUnit.MILLISECONDS)
/** Returns a [Duration] equal to this [Long] number of milliseconds. */
@SinceKotlin("1.3")
@ExperimentalTime
public val Long.milliseconds get() = toDuration(DurationUnit.MILLISECONDS)
/** Returns a [Duration] equal to this [Double] number of milliseconds. */
@SinceKotlin("1.3")
@ExperimentalTime
public val Double.milliseconds get() = toDuration(DurationUnit.MILLISECONDS)
/** Returns a [Duration] equal to this [Int] number of seconds. */
@SinceKotlin("1.3")
@ExperimentalTime
public val Int.seconds get() = toDuration(DurationUnit.SECONDS)
/** Returns a [Duration] equal to this [Long] number of seconds. */
@SinceKotlin("1.3")
@ExperimentalTime
public val Long.seconds get() = toDuration(DurationUnit.SECONDS)
/** Returns a [Duration] equal to this [Double] number of seconds. */
@SinceKotlin("1.3")
@ExperimentalTime
public val Double.seconds get() = toDuration(DurationUnit.SECONDS)
/** Returns a [Duration] equal to this [Int] number of minutes. */
@SinceKotlin("1.3")
@ExperimentalTime
public val Int.minutes get() = toDuration(DurationUnit.MINUTES)
/** Returns a [Duration] equal to this [Long] number of minutes. */
@SinceKotlin("1.3")
@ExperimentalTime
public val Long.minutes get() = toDuration(DurationUnit.MINUTES)
/** Returns a [Duration] equal to this [Double] number of minutes. */
@SinceKotlin("1.3")
@ExperimentalTime
public val Double.minutes get() = toDuration(DurationUnit.MINUTES)
/** Returns a [Duration] equal to this [Int] number of hours. */
@SinceKotlin("1.3")
@ExperimentalTime
public val Int.hours get() = toDuration(DurationUnit.HOURS)
/** Returns a [Duration] equal to this [Long] number of hours. */
@SinceKotlin("1.3")
@ExperimentalTime
public val Long.hours get() = toDuration(DurationUnit.HOURS)
/** Returns a [Duration] equal to this [Double] number of hours. */
@SinceKotlin("1.3")
@ExperimentalTime
public val Double.hours get() = toDuration(DurationUnit.HOURS)
/** Returns a [Duration] equal to this [Int] number of days. */
@SinceKotlin("1.3")
@ExperimentalTime
public val Int.days get() = toDuration(DurationUnit.DAYS)
/** Returns a [Duration] equal to this [Long] number of days. */
@SinceKotlin("1.3")
@ExperimentalTime
public val Long.days get() = toDuration(DurationUnit.DAYS)
/** Returns a [Duration] equal to this [Double] number of days. */
@SinceKotlin("1.3")
@ExperimentalTime
public val Double.days get() = toDuration(DurationUnit.DAYS)