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

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

    Details

    • Subcomponent:
    • Resolved In Build:
      b105
    • CPU:
      generic
    • OS:
      generic

      Description

      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;
          }


        Attachments

          Activity

            People

            • Assignee:
              ntv Nadeesh Tv
              Reporter:
              webbuggrp Webbug Group
            • Votes:
              0 Vote for this issue
              Watchers:
              6 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved: