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

Milliseconds computed by Calendar and Instant differ before 1893-04-01

    Details

    • Type: Bug
    • Status: Closed
    • Priority: P4
    • Resolution: Won't Fix
    • Affects Version/s: 8u20
    • Fix Version/s: None
    • Component/s: core-libs
    • Labels:

      Description

      FULL PRODUCT VERSION :
      java version "1.8.0_20"
      Java(TM) SE Runtime Environment (build 1.8.0_20-b26)
      Java HotSpot(TM) 64-Bit Server VM (build 25.20-b23, mixed mode)

      ADDITIONAL OS VERSION INFORMATION :
      Windows 7 64-bit
      Microsoft Windows [Version 6.1.7601]

      A DESCRIPTION OF THE PROBLEM :
      Using java.util.Calendar and java.time.Instant to compute the milliseconds since the epoch for a given java.time.LocalDate yields different values for dates before 1893-04-01.

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      Execute the attached test-program and see its Output:

      javac at/sphinx/bug/MillisecondTest.java
      java at.sphinx.bug.MillisecondTest
      pause

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      No output.
      ACTUAL -
      Date = 1916-10-01, Calendar = -1680483600000, Instant = -1680487200000, delta = -3600000 = PT-1H
      Date = 1916-09-30, Calendar = -1680573600000, Instant = -1680573600000, delta = 0 = PT0S
      Date = 1893-04-01, Calendar = -2422054800000, Instant = -2422054408000, delta = 392000 = PT6M32S
      Date = 1582-10-14, Calendar = -12218518800000, Instant = -12219382408000, delta = -863608000 = PT-239H-53M-28S
      Date = 1500-02-28, Calendar = -14825984400000, Instant = -14826761608000, delta = -777208000 = PT-215H-53M-28S
      Date = 1400-02-28, Calendar = -17981744400000, Instant = -17982435208000, delta = -690808000 = PT-191H-53M-28S
      Date = 1300-02-28, Calendar = -21137504400000, Instant = -21138108808000, delta = -604408000 = PT-167H-53M-28S
      Date = 1100-02-28, Calendar = -27449024400000, Instant = -27449542408000, delta = -518008000 = PT-143H-53M-28S
      Date = 1000-02-28, Calendar = -30604784400000, Instant = -30605216008000, delta = -431608000 = PT-119H-53M-28S
      Date = 0900-02-28, Calendar = -33760544400000, Instant = -33760889608000, delta = -345208000 = PT-95H-53M-28S
      Date = 0700-02-28, Calendar = -40072064400000, Instant = -40072323208000, delta = -258808000 = PT-71H-53M-28S
      Date = 0600-02-28, Calendar = -43227824400000, Instant = -43227996808000, delta = -172408000 = PT-47H-53M-28S
      Date = 0500-02-28, Calendar = -46383584400000, Instant = -46383670408000, delta = -86008000 = PT-23H-53M-28S
      Date = 0300-02-28, Calendar = -52695104400000, Instant = -52695104008000, delta = 392000 = PT6M32S
      Date = 0200-02-28, Calendar = -55850864400000, Instant = -55850777608000, delta = 86792000 = PT24H6M32S
      Date = 0100-02-28, Calendar = -59006624400000, Instant = -59006451208000, delta = 173192000 = PT48H6M32S

      REPRODUCIBILITY :
      This bug can be reproduced always.

      ---------- BEGIN SOURCE ----------
      package at.sphinx.bug;

      import java.time.Duration;
      import java.time.Instant;
      import java.time.LocalDate;
      import java.time.LocalDateTime;
      import java.time.ZoneId;
      import java.time.ZonedDateTime;
      import java.util.Calendar;

      @SuppressWarnings("nls")
      public class MillisecondTest
      {
          public static void main(String... arguments)
          {
              new MillisecondTest().performTest();
          }

          public void performTest()
          {
              LocalDate date = LocalDate.of(9999, 12, 31);
              long oldDelta = 0;
              while (date.getYear() >= 1)
              {
                  long millis1 = computeMillisUsingCalendar(date);
                  long millis2 = computeMillisUsingInstant(date);
                  long newDelta = millis2 - millis1;
                  if (newDelta != oldDelta)
                  {
                      System.out.printf("Date = %1$8s, Calendar = %2$15d, Instant = %3$15d, delta = %4$10d = %5$s\n",
                                        date, millis1, millis2, newDelta, Duration.ofMillis(newDelta));
                  }
                  oldDelta = newDelta;
                  date = date.minusDays(1);
              }
          }

          private long computeMillisUsingCalendar(LocalDate date)
          {
              Calendar vCalendar = Calendar.getInstance();
              vCalendar.clear();
              vCalendar.set(date.getYear(), date.getMonthValue() - 1, date.getDayOfMonth(), 0, 0, 0);
              return vCalendar.getTimeInMillis();
          }

          private long computeMillisUsingInstant(LocalDate date)
          {
              LocalDateTime dt = date.atStartOfDay();
              ZonedDateTime zdt = dt.atZone(ZoneId.systemDefault());
              Instant instant = zdt.toInstant();
              return instant.toEpochMilli();
          }
      }

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

      CUSTOMER SUBMITTED WORKAROUND :
      I used the conversion from a LocalDate to an Instant to get its milliseconds to instantiate a Java.utilDate that was sent to the JDBC Driver.

      I now use java.sql.Date.valueOf(LocalDate) to directly get a Java.sql.Date that is sent to the JDBC Driver.

        Attachments

          Issue Links

            Activity

              People

              • Assignee:
                okutsu Masayoshi Okutsu
                Reporter:
                webbuggrp Webbug Group
              • Votes:
                0 Vote for this issue
                Watchers:
                3 Start watching this issue

                Dates

                • Created:
                  Updated:
                  Resolved: