All Downloads are FREE. Search and download functionalities are using the official Maven repository.

scala.compat.java8.DurationConverters.scala Maven / Gradle / Ivy

/*
 * Scala (https://www.scala-lang.org)
 *
 * Copyright EPFL and Lightbend, Inc.
 *
 * Licensed under Apache License 2.0
 * (http://www.apache.org/licenses/LICENSE-2.0).
 *
 * See the NOTICE file distributed with this work for
 * additional information regarding copyright ownership.
 */

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 FiniteDuration.
   */
  final def toScala(duration: java.time.Duration): scala.concurrent.duration.FiniteDuration = {
    val originalSeconds = duration.getSeconds
    val originalNanos = duration.getNano
    if (originalNanos == 0) {
      if (originalSeconds == 0) ScalaDuration.Zero
      else FiniteDuration(originalSeconds, TimeUnit.SECONDS)
    } else if (originalSeconds == 0) {
      FiniteDuration(originalNanos, TimeUnit.NANOSECONDS)
    } else {
      try {
        val secondsAsNanos = Math.multiplyExact(originalSeconds, 1000000000)
        val totalNanos = secondsAsNanos + originalNanos
        if ((totalNanos < 0 && secondsAsNanos < 0) || (totalNanos > 0 && secondsAsNanos > 0)) FiniteDuration(totalNanos, TimeUnit.NANOSECONDS)
        else throw new ArithmeticException()
      } catch {
        case _: ArithmeticException => throw new IllegalArgumentException(s"Java duration $duration cannot be expressed as a Scala duration")
      }
    }
  }

  /**
   * Transform a Scala FiniteDuration 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.
   */
  final def toJava(duration: scala.concurrent.duration.FiniteDuration): java.time.Duration = {
    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)
    }
  }

  implicit final class DurationOps(val duration: java.time.Duration) extends AnyVal {
    /**
     * See [[DurationConverters#toScala]]
     */
    def toScala: scala.concurrent.duration.FiniteDuration = DurationConverters.toScala(duration)
  }

  implicit final class FiniteDurationops(val duration: scala.concurrent.duration.FiniteDuration) extends AnyVal {
    /**
     * See [[DurationConverters#toJava]]
     */
    def toJava: java.time.Duration = DurationConverters.toJava(duration)
  }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy