Converting Java to Scala durations

ScalaConfigDurationScala Java-Interop

Scala Problem Overview


Is there an elegant way to convert java.time.Duration to scala.concurrent.duration.FiniteDuration?

I am trying to do the following simple use of Config in Scala:

val d = ConfigFactory.load().getDuration("application.someTimeout")

However I don't see any simple way to use the result in Scala. Certainly hope the good people of Typesafe didn't expect me to do this:

FiniteDuration(d.getNano, TimeUnit.NANOSECONDS)

Edit: Note the line has a bug, which proves the point. See the selected answer below.

Scala Solutions


Solution 1 - Scala

I don't know whether an explicit conversion is the only way, but if you want to do it right

FiniteDuration(d.toNanos, TimeUnit.NANOSECONDS)

toNanos will return the total duration, while getNano will only return the nanoseconds component, which is not what you want.

E.g.

import java.time.Duration
import jata.time.temporal.ChronoUnit
Duration.of(1, ChronoUnit.HOURS).getNano // 0
Duration.of(1, ChronoUnit.HOURS).toNanos  // 3600000000000L

That being said, you can also roll your own implicit conversion

implicit def asFiniteDuration(d: java.time.Duration) =
  scala.concurrent.duration.Duration.fromNanos(d.toNanos)

and when you have it in scope:

val d: FiniteDuration = ConfigFactory.load().getDuration("application.someTimeout")

Solution 2 - Scala

Starting Scala 2.13, there is a dedicated DurationConverter from java's Duration to scala's FiniteDuration (and vice versa):

import scala.jdk.DurationConverters._

// val javaDuration = java.time.Duration.ofNanos(123456)
javaDuration.toScala
// scala.concurrent.duration.FiniteDuration = 123456 nanoseconds

Solution 3 - Scala

I don't know any better way, but you can make it a bit shorter:

Duration.fromNanos(d.toNanos)

and also wrap it into an implicit conversion yourself

implicit def toFiniteDuration(d: java.time.Duration): FiniteDuration = Duration.fromNanos(d.toNanos)

(changed d.toNano to d.toNanos)

Solution 4 - Scala

There is a function for this in scala-java8-compat

in build.sbt

libraryDependencies += "org.scala-lang.modules" %% "scala-java8-compat" % "0.9.0"
import scala.compat.java8.DurationConverters._

val javaDuration: java.time.Duration = ???
val scalaDuration: FiniteDuration = javaDuration.toScala

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionJacob EckelView Question on Stackoverflow
Solution 1 - ScalaGabriele PetronellaView Answer on Stackoverflow
Solution 2 - ScalaXavier GuihotView Answer on Stackoverflow
Solution 3 - ScalaTythView Answer on Stackoverflow
Solution 4 - ScalaStephenView Answer on Stackoverflow