8058429: JCK test api/java_sql/Timestamp/descriptions.html start failing after 8058230
authorredestad
Mon, 15 Sep 2014 21:20:46 +0200
changeset 26621 91ab384d2f49
parent 26620 6c427d708df2
child 26622 e7763eeb5e4d
8058429: JCK test api/java_sql/Timestamp/descriptions.html start failing after 8058230 Reviewed-by: lancea
jdk/src/java.sql/share/classes/java/sql/Timestamp.java
jdk/test/java/sql/test/sql/TimestampTests.java
--- a/jdk/src/java.sql/share/classes/java/sql/Timestamp.java	Mon Sep 15 13:05:04 2014 -0700
+++ b/jdk/src/java.sql/share/classes/java/sql/Timestamp.java	Mon Sep 15 21:20:46 2014 +0200
@@ -284,20 +284,32 @@
             }
         }
 
-        char[] buf = new char[29 - trailingZeros];
-        Date.formatDecimalInt(year, buf, 0, 4);
-        buf[4] = '-';
-        Date.formatDecimalInt(month, buf, 5, 2);
-        buf[7] = '-';
-        Date.formatDecimalInt(day, buf, 8, 2);
-        buf[10] = ' ';
-        Date.formatDecimalInt(hour, buf, 11, 2);
-        buf[13] = ':';
-        Date.formatDecimalInt(minute, buf, 14, 2);
-        buf[16] = ':';
-        Date.formatDecimalInt(second, buf, 17, 2);
-        buf[19] = '.';
-        Date.formatDecimalInt(tmpNanos, buf, 20, 9 - trailingZeros);
+        // 8058429: To comply with current JCK tests, we need to deal with year
+        // being any number between 0 and 292278995
+        int count = 10000;
+        int yearSize = 4;
+        do {
+            if (year < count) {
+                break;
+            }
+            yearSize++;
+            count *= 10;
+        } while (count < 1000000000);
+
+        char[] buf = new char[25 + yearSize - trailingZeros];
+        Date.formatDecimalInt(year, buf, 0, yearSize);
+        buf[yearSize] = '-';
+        Date.formatDecimalInt(month, buf, yearSize + 1, 2);
+        buf[yearSize + 3] = '-';
+        Date.formatDecimalInt(day, buf, yearSize + 4, 2);
+        buf[yearSize + 6] = ' ';
+        Date.formatDecimalInt(hour, buf, yearSize + 7, 2);
+        buf[yearSize + 9] = ':';
+        Date.formatDecimalInt(minute, buf, yearSize + 10, 2);
+        buf[yearSize + 12] = ':';
+        Date.formatDecimalInt(second, buf, yearSize + 13, 2);
+        buf[yearSize + 15] = '.';
+        Date.formatDecimalInt(tmpNanos, buf, yearSize + 16, 9 - trailingZeros);
 
         return jla.newStringUnsafe(buf);
     }
--- a/jdk/test/java/sql/test/sql/TimestampTests.java	Mon Sep 15 13:05:04 2014 -0700
+++ b/jdk/test/java/sql/test/sql/TimestampTests.java	Mon Sep 15 21:20:46 2014 +0200
@@ -27,6 +27,7 @@
 import java.sql.Timestamp;
 import java.time.Instant;
 import java.time.LocalDateTime;
+import java.time.ZoneId;
 import java.util.Calendar;
 import static org.testng.Assert.*;
 import org.testng.annotations.DataProvider;
@@ -610,6 +611,12 @@
                 "Error with Nanos");
     }
 
+    @Test(dataProvider = "validTimestampLongValues")
+    public void test52(long value, String ts) {
+        Timestamp ts1 = new Timestamp(value);
+        assertEquals(ts1.toString(), ts, "ts1.toString() != ts");
+    }
+
     /*
      * DataProvider used to provide Timestamps which are not valid and are used
      * to validate that an IllegalArgumentException will be thrown from the
@@ -678,6 +685,40 @@
         };
     }
 
+    @DataProvider(name = "validTimestampLongValues")
+    private Object[][] validTimestampLongValues() {
+        return new Object[][]{
+            {1L, "1970-01-01 01:00:00.001"},
+            {-3600*1000L - 1, "1969-12-31 23:59:59.999"},
+            {-(20000L*365*24*60*60*1000), "18018-08-28 01:00:00.0"},
+            {Timestamp.valueOf("1961-08-30 11:22:33").getTime(), "1961-08-30 11:22:33.0"},
+            {Timestamp.valueOf("1961-08-30 11:22:33.54321000").getTime(), "1961-08-30 11:22:33.543"}, // nanoprecision lost
+            {new Timestamp(114, 10, 10, 10, 10, 10, 100000000).getTime(), "2014-11-10 10:10:10.1"},
+            {new Timestamp(0, 10, 10, 10, 10, 10, 100000).getTime(), "1900-11-10 10:10:10.0"}, // nanoprecision lost
+            {new Date(114, 10, 10).getTime(), "2014-11-10 00:00:00.0"},
+            {new Date(0, 10, 10).getTime(), "1900-11-10 00:00:00.0"},
+            {LocalDateTime.of(1960, 10, 10, 10, 10, 10, 50000).atZone(ZoneId.of("America/Los_Angeles"))
+                .toInstant().toEpochMilli(), "1960-10-10 19:10:10.0"},
+
+            // millisecond timestamps wraps around at year 1, so Long.MIN_VALUE looks similar
+            // Long.MAX_VALUE, while actually representing 292278994 BCE
+            {Long.MIN_VALUE, "292278994-08-17 08:12:55.192"},
+            {Long.MAX_VALUE + 1, "292278994-08-17 08:12:55.192"},
+            {Long.MAX_VALUE, "292278994-08-17 08:12:55.807"},
+            {Long.MIN_VALUE - 1, "292278994-08-17 08:12:55.807"},
+
+            // wrap around point near 0001-01-01, test that we never get a negative year:
+            {-(1970L*365*24*60*60*1000), "0001-04-25 01:00:00.0"},
+            {-(1970L*365*24*60*60*1000 + 115*24*60*60*1000L), "0001-12-31 01:00:00.0"},
+            {-(1970L*365*24*60*60*1000 + 115*24*60*60*1000L - 23*60*60*1000L), "0001-01-01 00:00:00.0"},
+
+            {LocalDateTime.of(0, 1, 1, 10, 10, 10, 50000).atZone(ZoneId.of("America/Los_Angeles"))
+                .toInstant().toEpochMilli() - 2*24*60*60*1000L, "0001-01-01 19:03:08.0"}, // 1 BCE
+            {LocalDateTime.of(0, 1, 1, 10, 10, 10, 50000).atZone(ZoneId.of("America/Los_Angeles"))
+                .toInstant().toEpochMilli() - 3*24*60*60*1000L, "0002-12-31 19:03:08.0"} // 2 BCE
+        };
+    }
+
     /*
      * DataProvider used to provide Timestamp and Nanos values in order to
      * validate that the correct Nanos value is generated from the specified