From ff9d2744ce9b63321504cb70cf500bb99bc59f75 Mon Sep 17 00:00:00 2001 From: Ilya Gorbunov Date: Tue, 18 Jun 2019 05:35:29 +0300 Subject: [PATCH] Provide conversions between Kotlin and Java time durations --- .../src/kotlin/time/DurationConversions.kt | 35 +++++++++ .../jdk8/test/time/DurationConversionTest.kt | 72 +++++++++++++++++++ 2 files changed, 107 insertions(+) create mode 100644 libraries/stdlib/jdk8/src/kotlin/time/DurationConversions.kt create mode 100644 libraries/stdlib/jdk8/test/time/DurationConversionTest.kt diff --git a/libraries/stdlib/jdk8/src/kotlin/time/DurationConversions.kt b/libraries/stdlib/jdk8/src/kotlin/time/DurationConversions.kt new file mode 100644 index 00000000000..1de8e33fdbe --- /dev/null +++ b/libraries/stdlib/jdk8/src/kotlin/time/DurationConversions.kt @@ -0,0 +1,35 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +@file:Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE") +@file:JvmName("DurationConversionsJDK8Kt") +@file:kotlin.jvm.JvmPackageName("kotlin.time.jdk8") +package kotlin.time + +import java.time.* + +/** + * Converts [java.time.Duration][java.time.Duration] value to [kotlin.time.Duration][Duration] value. + * + * Durations less than 104 days are converted exactly, and durations greater than that can lose some precision + * due to rounding. + */ +@SinceKotlin("1.3") +@ExperimentalTime +@kotlin.internal.InlineOnly +public inline fun java.time.Duration.toKotlinDuration(): Duration = + this.seconds.seconds + this.nano.nanoseconds + + +/** + * Converts [kotlin.time.Duration][Duration] value to value [java.time.Duration][java.time.Duration]. + * + * Durations greater than [Long.MAX_VALUE] seconds are cut to that value. + */ +@SinceKotlin("1.3") +@ExperimentalTime +@kotlin.internal.InlineOnly +public inline fun Duration.toJavaDuration(): java.time.Duration = + toComponents { seconds, nanoseconds -> java.time.Duration.ofSeconds(seconds, nanoseconds.toLong()) } \ No newline at end of file diff --git a/libraries/stdlib/jdk8/test/time/DurationConversionTest.kt b/libraries/stdlib/jdk8/test/time/DurationConversionTest.kt new file mode 100644 index 00000000000..9cbb31bd3be --- /dev/null +++ b/libraries/stdlib/jdk8/test/time/DurationConversionTest.kt @@ -0,0 +1,72 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +@file:UseExperimental(ExperimentalTime::class) + +package kotlin.jdk8.time.test + +import kotlin.random.Random +import kotlin.test.* +import kotlin.time.* +import java.time.Duration as JTDuration + +class DurationConversionTest { + @Test + fun twoWayConversion() { + fun test(days: Int, hours: Int, minutes: Int, seconds: Int, millis: Int, nanos: Int) { + val duration = days.days + hours.hours + minutes.minutes + seconds.seconds + millis.milliseconds + nanos.nanoseconds + val jtDuration = JTDuration.ZERO + .plusDays(days.toLong()) + .plusHours(hours.toLong()) + .plusMinutes(minutes.toLong()) + .plusSeconds(seconds.toLong()) + .plusMillis(millis.toLong()) + .plusNanos(nanos.toLong()) + + assertEquals(jtDuration, duration.toJavaDuration()) + assertEquals(duration, jtDuration.toKotlinDuration()) + } + + repeat(100) { + test( + days = Random.nextInt(-100, 100), + hours = Random.nextInt(-48, 48), + minutes = Random.nextInt(-600, 600), + seconds = Random.nextInt(-600, 600), + millis = Random.nextInt(-1000000, 1000000), + nanos = Random.nextInt() + ) + } + } + + @Test + fun javaToKotlinRounding() { + val jtDuration = JTDuration.ofDays(105).plusNanos(1) + val duration = jtDuration.toKotlinDuration() + assertEquals(105.days, duration) + } + + @Test + fun kotlinToJavaClamping() { + val duration = Long.MAX_VALUE.seconds * 5 + val jtDuration = duration.toJavaDuration() + assertEquals(JTDuration.ofSeconds(Long.MAX_VALUE), jtDuration) + + val jtnegDuration = (-duration).toJavaDuration() + assertEquals(JTDuration.ofSeconds(Long.MIN_VALUE), jtnegDuration) + } + + @Test + fun randomIsoConversionEquivalence() { + repeat(100) { + val duration = Random.nextLong(-(1 shl 53) + 1, 1 shl 53).nanoseconds + val fromString = JTDuration.parse(duration.toIsoString()) + val fromDuration = duration.toJavaDuration() + + assertEquals(fromString, fromDuration) + } + } +} +