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

DateTimeException thrown when calculating duration between certain dates

    XMLWordPrintable

Details

    • b10
    • generic
    • generic

    Description

      ADDITIONAL SYSTEM INFORMATION :
      → java --version
      openjdk 11 2018-09-25
      OpenJDK Runtime Environment AdoptOpenJDK (build 11+28)
      OpenJDK 64-Bit Server VM AdoptOpenJDK (build 11+28, mixed mode)

      A DESCRIPTION OF THE PROBLEM :
      There are certain dates/times (at least OffsetDateTime possibly others with time zone information) which seem trivial to calculate the duration between but they fail with a java.time.DateTimeException.

      The issue is that Duration.between will call until() which, in the case of OffsetDateTime, will call withOffsetSameInstant(). This is not always a valid thing to do since not all instants are valid in every time zone.

      In my opinion it seems that the root of the issue is a design flaw in OffsetDateTime which it can represent an instant that cannot be converted to the same instant in a different time zone. OffsetDateTime.MAX for example is only valid in ZoneOffset.MIN. While OffsetDateTime.MAX is technically the latest on the time-line it is still just arbitrary and should have been LocalDateTime.MAX with ZoneOffset.MAX. The implications of this are that there needs to be a lot of defensive programming to handle OffsetDateTime's that are close to the extremities. This may be rare but is an annoying case that shouldn't exist. It is possibly too late to change this, however the methods in java.time should at least handle it correctly.

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      → jshell
      | Welcome to JShell -- Version 11
      | For an introduction type: /help intro

      jshell> import java.time.OffsetDateTime

      jshell> import java.time.Duration

      jshell> import java.time.ZoneOffset

      jshell> var a = OffsetDateTime.MAX.minusHours(1).withOffsetSameLocal(ZoneOffset.ofHours(-17))
      a ==> +999999999-12-31T22:59:59.999999999-17:00

      jshell> var b = OffsetDateTime.MAX
      b ==> +999999999-12-31T23:59:59.999999999-18:00

      jshell> Duration.between(a, b)

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      $7 ==> PT1H
      ACTUAL -
      | Exception java.time.DateTimeException: Invalid value for Year (valid values -999999999 - 999999999): 1000000000
      | at ValueRange.checkValidValue (ValueRange.java:311)
      | at ChronoField.checkValidValue (ChronoField.java:717)
      | at LocalDate.plusDays (LocalDate.java:1386)
      | at LocalDateTime.plusWithOverflow (LocalDateTime.java:1571)
      | at LocalDateTime.plusSeconds (LocalDateTime.java:1327)
      | at OffsetDateTime.withOffsetSameInstant (OffsetDateTime.java:701)
      | at OffsetDateTime.until (OffsetDateTime.java:1657)
      | at Duration.between (Duration.java:490)
      | at (#6:1)

      CUSTOMER SUBMITTED WORKAROUND :
      You have to first check if the OffsetDateTime is close to the min or max and if it is then manually adjust the offsets into the one which will be within the bounds.

      FREQUENCY : always


      Attachments

        Activity

          People

            naoto Naoto Sato
            webbuggrp Webbug Group
            Votes:
            0 Vote for this issue
            Watchers:
            4 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved: