-
Notifications
You must be signed in to change notification settings - Fork 102
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
2030bfa
commit 6ecc420
Showing
2 changed files
with
173 additions
and
0 deletions.
There are no files selected for viewing
61 changes: 61 additions & 0 deletions
61
src/main/scala/scala/compat/java8/DurationConverters.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
/* | ||
* Copyright (C) 2012-2017 Typesafe Inc. <http://www.typesafe.com> | ||
*/ | ||
package scala.compat.java8 | ||
|
||
import java.time.temporal.ChronoUnit | ||
import java.util.concurrent.TimeUnit | ||
import java.time.{Duration => JavaDuration} | ||
|
||
import scala.concurrent.duration.{FiniteDuration, Duration => ScalaDuration} | ||
|
||
|
||
/** | ||
* This class contains static methods which convert between Java Durations | ||
* and the durations from the Scala concurrency package. This is useful when mediating between Scala and Java | ||
* libraries with asynchronous APIs where timeouts for example are often expressed as durations. | ||
*/ | ||
object DurationConverters { | ||
|
||
/** | ||
* Transform a Java duration into a Scala duration. If the nanosecond part of the Java duration is zero the returned | ||
* duration will have a time unit of seconds and if there is a nanoseconds part the Scala duration will have a time | ||
* unit of nanoseconds. | ||
* | ||
* @throws IllegalArgumentException If the given Java Duration is out of bounds of what can be expressed with the | ||
* Scala Durations. | ||
*/ | ||
final def toScala(duration: java.time.Duration): scala.concurrent.duration.Duration = { | ||
if (duration.getNano == 0) { | ||
if (duration.getSeconds == 0) ScalaDuration.Zero | ||
else FiniteDuration(duration.getSeconds, TimeUnit.SECONDS) | ||
} else { | ||
FiniteDuration( | ||
duration.getSeconds * 1000000000 + duration.getNano, | ||
TimeUnit.NANOSECONDS | ||
) | ||
} | ||
} | ||
|
||
/** | ||
* Transform a Scala duration into a Java duration. Note that the Scala duration keeps the time unit it was created | ||
* with while a Java duration always is a pair of seconds and nanos, so the unit it lost. | ||
* | ||
* @throws IllegalArgumentException If the Scala duration express a amount of time for the time unit that | ||
* a Java Duration can not express (infinite durations and undefined durations) | ||
*/ | ||
final def toJava(duration: scala.concurrent.duration.Duration): java.time.Duration = { | ||
require(duration.isFinite(), s"Got [$duration] but only finite Scala durations can be expressed as a Java Durations") | ||
if (duration.length == 0) JavaDuration.ZERO | ||
else duration.unit match { | ||
case TimeUnit.NANOSECONDS => JavaDuration.ofNanos(duration.length) | ||
case TimeUnit.MICROSECONDS => JavaDuration.of(duration.length, ChronoUnit.MICROS) | ||
case TimeUnit.MILLISECONDS => JavaDuration.ofMillis(duration.length) | ||
case TimeUnit.SECONDS => JavaDuration.ofSeconds(duration.length) | ||
case TimeUnit.MINUTES => JavaDuration.ofMinutes(duration.length) | ||
case TimeUnit.HOURS => JavaDuration.ofHours(duration.length) | ||
case TimeUnit.DAYS => JavaDuration.ofDays(duration.length) | ||
} | ||
} | ||
|
||
} |
112 changes: 112 additions & 0 deletions
112
src/test/scala/scala/compat/java8/DurationConvertersTest.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,112 @@ | ||
/* | ||
* Copyright (C) 2009-2017 Lightbend Inc. <http://www.lightbend.com> | ||
*/ | ||
package scala.compat.java8 | ||
|
||
import org.junit.Test | ||
import org.junit.Assert._ | ||
import java.time.{Duration => JavaDuration} | ||
|
||
import scala.util.Try | ||
|
||
class DurationConvertersTest { | ||
|
||
import DurationConverters._ | ||
import scala.concurrent.duration._ | ||
|
||
@Test | ||
def scalaNanosToJavaDuration(): Unit = { | ||
Seq[(Long, (Long, Int))]( | ||
(Long.MinValue + 1) -> (-9223372037L, 145224193), // because java duration nanos are offset from the "wrong" direction | ||
-1000000001L -> (-2, 999999999), | ||
-1L -> (-1, 999999999), | ||
0L -> (0, 0), | ||
1L -> (0, 1), | ||
1000000001L -> (1,1), | ||
Long.MaxValue -> (9223372036L, 854775807) | ||
).foreach { case (n, (expSecs, expNanos)) => | ||
val result = toJava(n.nanos) | ||
assertEquals(s"toJava($n nanos) -> $expSecs s)", expSecs, result.getSeconds) | ||
assertEquals(s"toJava($n nanos) -> $expNanos n)", expNanos, result.getNano) | ||
} | ||
} | ||
|
||
@Test | ||
def scalaMilliSecondsToJavaDuration(): Unit = { | ||
Seq[(Long, (Long, Int))]( | ||
-9223372036854L -> (-9223372037L, 146000000), | ||
-1L -> (-1L, 999000000), | ||
0L -> (0L, 0), | ||
1L -> (0L, 1000000), | ||
9223372036854L -> (9223372036L, 854000000) | ||
).foreach { case (n, (expSecs, expNanos)) => | ||
val result = toJava(n.millis) | ||
assertEquals(s"toJava($n millis) -> $expSecs s)", expSecs, result.getSeconds) | ||
assertEquals(s"toJava($n millis) -> $expNanos n)", expNanos, result.getNano) | ||
} | ||
} | ||
|
||
@Test | ||
def scalaMicroSecondsToJavaDuration(): Unit = { | ||
Seq[(Long, (Long, Int))]( | ||
-9223372036854775L -> (-9223372037L, 145225000), | ||
-1L -> (-1L, 999999000), | ||
0L -> (0L, 0), | ||
1L -> (0L, 1000), | ||
9223372036854775L -> (9223372036L, 854775000) | ||
).foreach { case (n, (expSecs, expNanos)) => | ||
val result = toJava(n.micros) | ||
assertEquals(s"toJava($n micros) -> $expSecs s)", expSecs, result.getSeconds) | ||
assertEquals(s"toJava($n micros) -> $expNanos n)", expNanos, result.getNano) | ||
} | ||
} | ||
|
||
@Test | ||
def scalaSecondsToJavaDuration(): Unit = { | ||
Seq[(Long, (Long, Int))]( | ||
-9223372036L -> (-9223372036L, 0), | ||
-1L -> (-1L, 0), | ||
0L -> (0L, 0), | ||
1L -> (1L, 0), | ||
9223372036L -> (9223372036L, 0) | ||
).foreach { case (n, (expSecs, expNanos)) => | ||
val result = toJava(n.seconds) | ||
assertEquals(expSecs, result.getSeconds) | ||
assertEquals(expNanos, result.getNano) | ||
} | ||
} | ||
|
||
|
||
@Test | ||
def javaSecondsToScalaDuration(): Unit = { | ||
Seq[Long](-9223372036L, -1L, 0L, 1L, 9223372036L).foreach { n => | ||
assertEquals(n, toScala(JavaDuration.ofSeconds(n)).toSeconds) | ||
} | ||
} | ||
|
||
|
||
@Test | ||
def javaNanosPartToScalaDuration(): Unit = { | ||
Seq[Long](Long.MinValue + 1L, -1L, 0L, 1L, Long.MaxValue).foreach { n => | ||
assertEquals(n, toScala(JavaDuration.ofNanos(n)).toNanos) | ||
} | ||
} | ||
|
||
@Test | ||
def unsupportedScalaDurationThrows(): Unit = { | ||
Seq(Duration.Inf, Duration.MinusInf, Duration.Undefined).foreach { d => | ||
val res = Try { toJava(d) } | ||
assertTrue(s"Expected exception for $d but got success", res.isFailure) | ||
} | ||
} | ||
|
||
@Test | ||
def unsupportedJavaDurationThrows(): Unit = { | ||
Seq(JavaDuration.ofSeconds(-9223372037L), JavaDuration.ofSeconds(9223372037L)).foreach { d => | ||
val res = Try { toScala(d) } | ||
assertTrue(s"Expected exception for $d but got success", res.isFailure) | ||
} | ||
} | ||
|
||
|
||
} |