Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8146747

java.time.Duration.toNanos() and toMillis() exception on negative durations

XMLWordPrintable

    • b105
    • generic
    • generic

      FULL PRODUCT VERSION :
      java version "1.8.0_66"
      Java(TM) SE Runtime Environment (build 1.8.0_66-b18)
      Java HotSpot(TM) 64-Bit Server VM (build 25.66-b18, mixed mode)

      A DESCRIPTION OF THE PROBLEM :
      java.time.Duration.toNanos() and toMillis() throw an ArithmeticException on an intermediate calculation when the duration is very close to, but greater than Long.MIN_VALUE nanoseconds or milliseconds, respectively.

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      Duration.ofNanos(Long.MIN_VALUE).toNanos();

      Duration.ofMillis(Long.MIN_VALUE).toMillis();


      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      Expected result from each statement is Long.MIN_VALUE.
      ACTUAL -
      Both the statements throw ArithmeticException.

      REPRODUCIBILITY :
      This bug can be reproduced always.

      ---------- BEGIN SOURCE ----------
      public class Bug {
          public static void main(String[] args) {
              // uncomment following line for toNanos() bug
              // Duration.ofNanos(Long.MIN_VALUE).toNanos();
              Duration.ofMillis(Long.MIN_VALUE).toMillis();
          }
      }

      ---------- END SOURCE ----------

      CUSTOMER SUBMITTED WORKAROUND :
      The following implementations of toNanos() and toMillis() fix the problem:

          public long toMillis() {
              long millis;
              if (isNegative()) {
                  millis = Math.multiplyExact(seconds + 1, 1000);
                  millis = Math.addExact(millis, nanos / 1000_000 - 1000);
              }
              else {
                  millis = Math.multiplyExact(seconds, 1000);
                  millis = Math.addExact(millis, nanos / 1000_000);
              }
              return millis;
          }

          public long toNanos() {
              long totalNanos;
              if (isNegative()) {
                  totalNanos = Math.multiplyExact(seconds() + 1, NANOS_PER_SECOND);
                  totalNanos = Math.addExact(totalNanos, nanos - NANOS_PER_SECOND);
              }
              else {
                  totalNanos = Math.multiplyExact(seconds, NANOS_PER_SECOND);
                  totalNanos = Math.addExact(totalNanos, nanos);
              }
              return totalNanos;
          }


            ntv Nadeesh Tv
            webbuggrp Webbug Group
            Votes:
            0 Vote for this issue
            Watchers:
            8 Start watching this issue

              Created:
              Updated:
              Resolved: