| /* |
| * Copyright 2018 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| @file:kotlin.jvm.JvmName("Durations") |
| @file:Suppress("NOTHING_TO_INLINE") |
| |
| package androidx.compose.ui.unit |
| |
| import androidx.compose.runtime.Immutable |
| import androidx.compose.runtime.Stable |
| |
| /* |
| * The following unit conversion factors are required to be public due to their use |
| * from inline functions. |
| */ |
| |
| const val NanosecondsPerMicrosecond = 1000L |
| const val MicrosecondsPerMillisecond = 1000L |
| const val MillisecondsPerSecond = 1000L |
| const val SecondsPerMinute = 60L |
| const val MinutesPerHour = 60L |
| const val HoursPerDay = 24L |
| |
| // TODO(mount): these should be "const val", but that doesn't work right |
| // now with the IR compiler. |
| val NanosecondsPerMillisecond = NanosecondsPerMicrosecond * MicrosecondsPerMillisecond |
| val NanosecondsPerSecond = NanosecondsPerMillisecond * MillisecondsPerSecond |
| val NanosecondsPerMinute = NanosecondsPerSecond * SecondsPerMinute |
| val NanosecondsPerHour = NanosecondsPerMinute * MinutesPerHour |
| val NanosecondsPerDay = NanosecondsPerHour * HoursPerDay |
| |
| /** Only used by this implementation */ |
| private const val MicrosecondsPerSecond = MicrosecondsPerMillisecond * MillisecondsPerSecond |
| |
| /** |
| * Constructs a [Duration] given a series of time intervals in different units. |
| */ |
| fun Duration( |
| days: Long = 0, |
| hours: Long = 0, |
| minutes: Long = 0, |
| seconds: Long = 0, |
| milliseconds: Long = 0, |
| microseconds: Long = 0, |
| nanoseconds: Long = 0 |
| ) = Duration( |
| days * NanosecondsPerDay + |
| hours * NanosecondsPerHour + |
| minutes * NanosecondsPerMinute + |
| seconds * NanosecondsPerSecond + |
| milliseconds * NanosecondsPerMillisecond + |
| microseconds * NanosecondsPerMicrosecond + |
| nanoseconds |
| ) |
| |
| /* A [Duration] of this many days. */ |
| // TODO(inline) |
| val Long.days: Duration get() = Duration(this * NanosecondsPerDay) |
| |
| /* A [Duration] of this many hours. */ |
| // TODO(inline) |
| val Long.hours: Duration get() = Duration(this * NanosecondsPerHour) |
| |
| /* A [Duration] of this many minutes. */ |
| // TODO(inline) |
| val Long.minutes: Duration get() = Duration(this * NanosecondsPerMinute) |
| |
| /* A [Duration] of this many seconds. */ |
| // TODO(inline) |
| val Long.seconds: Duration get() = Duration(this * NanosecondsPerSecond) |
| |
| /* A [Duration] of this many milliseconds. */ |
| // TODO(inline) |
| val Long.milliseconds: Duration get() = Duration(this * NanosecondsPerMillisecond) |
| |
| /* A [Duration] of this many microseconds. */ |
| // TODO(inline) |
| val Long.microseconds: Duration get() = Duration(this * NanosecondsPerMicrosecond) |
| |
| /* A [Duration] of this many nanoseconds. */ |
| // TODO(inline) |
| val Long.nanoseconds: Duration get() = Duration(this) |
| |
| /* A [Duration] of this many days. */ |
| // TODO(inline) |
| val Int.days: Duration get() = toLong().days |
| |
| /* A [Duration] of this many hours. */ |
| // TODO(inline) |
| val Int.hours: Duration get() = toLong().hours |
| |
| /* A [Duration] of this many minutes. */ |
| // TODO(inline) |
| val Int.minutes: Duration get() = toLong().minutes |
| |
| /* A [Duration] of this many seconds. */ |
| // TODO(inline) |
| val Int.seconds: Duration get() = toLong().seconds |
| |
| /* A [Duration] of this many milliseconds. */ |
| // TODO(inline) |
| val Int.milliseconds: Duration get() = toLong().milliseconds |
| |
| /* A [Duration] of this many microseconds. */ |
| // TODO(inline) |
| val Int.microseconds: Duration get() = toLong().microseconds |
| |
| /* A [Duration] of this many nanoseconds. */ |
| // TODO(inline) |
| val Int.nanoseconds: Duration get() = toLong().nanoseconds |
| |
| /** |
| * A span of time, such as 27 days, 4 hours, 12 minutes, and 3 seconds. |
| * |
| * A [Duration] represents a difference from one point in time to another. The |
| * duration may be "negative" if the difference is from a later time to an |
| * earlier. |
| * |
| * Durations are context independent. For example, a duration of 2 days is |
| * always 48 hours, even when it is added to a `DateTime` just when the |
| * time zone is about to do a daylight-savings switch. |
| * |
| * Despite the same name, a [Duration] object does not implement "Durations" |
| * as specified by ISO 8601. In particular, a duration object does not keep |
| * track of the individually provided members (such as "days" or "hours"), but |
| * only uses these arguments to compute the length of the corresponding time |
| * interval. |
| * |
| * To create a [Duration], use the unit extension functions on the primitive |
| * `Int` and `Long` types: |
| * |
| * val aLongWeekend = 96.hours |
| * |
| * To create a [Duration] from several components, use the [Duration] factory function: |
| * |
| * val fastestMarathon = Duration(hours = 2, minutes = 3, seconds = 2) |
| * |
| * The [Duration] is the sum of all individual parts. |
| * This means that individual parts can be larger than the next-bigger unit. |
| * For example, [inMinutes] can be greater than 59. |
| * |
| * assertEquals(123, fastestMarathon.inMinutes) |
| * |
| * All individual parts are allowed to be negative. |
| * |
| * Use one of the extensions such as [inDays] to retrieve the integer value of the Duration |
| * in the specified time unit. Note that the returned value is rounded down. |
| * For example, |
| * |
| * val aLongWeekend = 86.hours |
| * assertEquals(3, aLongWeekend.inDays()) |
| */ |
| @Immutable |
| data class Duration(val nanoseconds: Long) : Comparable<Duration> { |
| |
| /** |
| * Adds this Duration and [other] and returns the sum as a Duration. |
| */ |
| @Stable |
| operator fun plus(other: Duration) = Duration(nanoseconds + other.nanoseconds) |
| |
| /** |
| * Subtracts [other] from this Duration and returns the difference. |
| */ |
| @Stable |
| operator fun minus(other: Duration) = Duration(nanoseconds - other.nanoseconds) |
| |
| /** |
| * Multiplies this Duration by the given [factor] and returns the result. |
| */ |
| @Stable |
| operator fun times(factor: Int) = Duration(nanoseconds * factor) |
| |
| /** |
| * Multiplies this Duration by the given [factor] and returns the result. |
| */ |
| @Stable |
| operator fun times(factor: Double) = Duration((nanoseconds * factor).toLong()) |
| |
| /** |
| * Divides this Duration by the given [quotient] and returns the truncated |
| * result as a Duration. |
| */ |
| @Stable |
| operator fun div(quotient: Int) = Duration(nanoseconds / quotient) |
| |
| /** |
| * Divides this Duration by the given [quotient] and returns the truncated |
| * result as a Duration. |
| */ |
| @Stable |
| operator fun div(quotient: Double) = Duration((nanoseconds / quotient).toLong()) |
| |
| /** |
| * Compares this Duration to [other], returning zero if the values are equal. |
| * |
| * Returns a negative integer if this [Duration] is shorter than |
| * [other], or a positive integer if it is longer. |
| * |
| * A negative [Duration] is always considered shorter than a positive one. |
| * |
| * It is always the case that `duration1.compareTo(duration2) < 0` if |
| * `(someDate + duration1).compareTo(someDate + duration2) < 0`. |
| */ |
| @Stable |
| override fun compareTo(other: Duration): Int = when { |
| nanoseconds < other.nanoseconds -> -1 |
| nanoseconds == other.nanoseconds -> 0 |
| else -> 1 |
| } |
| |
| /** |
| * Returns a string representation of this [Duration]. |
| * |
| * Returns a string with hours, minutes, seconds, and microseconds, in the |
| * following format: `HH:MM:SS.mmmmmm`. For example, |
| * |
| * val d = Duration(days = 1, hours = 1, minutes = 33, microseconds = 500) |
| * d.toString() // "25:33:00.000500" |
| */ |
| @Stable |
| override fun toString(): String { |
| if (inMicroseconds() < 0) { |
| return "-${Duration(-nanoseconds)}" |
| } |
| val twoDigitMinutes = inMinutes().rem(MinutesPerHour).toString().padStart(2, '0') |
| val twoDigitSeconds = inSeconds().rem(SecondsPerMinute).toString().padStart(2, '0') |
| val sixDigitUs = inMicroseconds().rem(MicrosecondsPerSecond).toString().padStart(6, '0') |
| return "${inHours()}:$twoDigitMinutes:$twoDigitSeconds.$sixDigitUs" |
| } |
| |
| companion object { |
| /** An empty Duration. No delay. Instant. */ |
| @Stable |
| val Zero = Duration(0) |
| } |
| } |
| |
| /* |
| * API note: The `inUnits()` functions below are not `toUnits()` because they do not |
| * perform type conversion. They are also functions rather than properties to highlight |
| * that they are truncating conversions of the whole value, not hours/minutes-style components |
| * isolated from each other available unit. |
| */ |
| |
| /** |
| * Returns the number of whole days spanned by this Duration. |
| */ |
| // TODO(inline) |
| fun Duration.inDays(): Long = nanoseconds / NanosecondsPerDay |
| |
| /** |
| * Returns the number of whole hours spanned by this Duration. |
| * |
| * The returned value can be greater than 23. |
| */ |
| // TODO(inline) |
| fun Duration.inHours(): Long = nanoseconds / NanosecondsPerHour |
| |
| /** |
| * Returns the number of whole minutes spanned by this Duration. |
| * |
| * The returned value can be greater than 59. |
| */ |
| // TODO(inline) |
| fun Duration.inMinutes(): Long = nanoseconds / NanosecondsPerMinute |
| |
| /** |
| * Returns the number of whole seconds spanned by this Duration. |
| * |
| * The returned value can be greater than 59. |
| */ |
| // TODO(inline) |
| fun Duration.inSeconds(): Long = nanoseconds / NanosecondsPerSecond |
| |
| /** |
| * Returns number of whole milliseconds spanned by this Duration. |
| * |
| * The returned value can be greater than 999. |
| */ |
| // TODO(inline) |
| fun Duration.inMilliseconds(): Long = nanoseconds / NanosecondsPerMillisecond |
| |
| /** |
| * Returns number of whole microseconds spanned by this Duration. |
| */ |
| // TODO(inline) |
| fun Duration.inMicroseconds(): Long = nanoseconds / NanosecondsPerMicrosecond |