8079628: java.time: DateTimeFormatter containing "DD" fails on 3-digit day-of-year value`
authorntv
Sun, 08 May 2016 07:46:19 +0000
changeset 37812 6fd749bfad2d
parent 37811 40c09ac0ca71
child 37813 874f4ca115c3
8079628: java.time: DateTimeFormatter containing "DD" fails on 3-digit day-of-year value` Summary: Change the definition of 'DD' to match with CLDR Reviewed-by: rriggs, scolebourne
jdk/src/java.base/share/classes/java/time/format/DateTimeFormatterBuilder.java
jdk/test/java/time/tck/java/time/format/TCKDateTimeFormatterBuilder.java
jdk/test/java/time/test/java/time/format/TestDateTimeFormatterBuilder.java
--- a/jdk/src/java.base/share/classes/java/time/format/DateTimeFormatterBuilder.java	Sat May 07 08:44:48 2016 +0200
+++ b/jdk/src/java.base/share/classes/java/time/format/DateTimeFormatterBuilder.java	Sun May 08 07:46:19 2016 +0000
@@ -1488,7 +1488,7 @@
      *    d       1      appendValue(ChronoField.DAY_OF_MONTH)
      *    dd      2      appendValue(ChronoField.DAY_OF_MONTH, 2)
      *    D       1      appendValue(ChronoField.DAY_OF_YEAR)
-     *    DD      2      appendValue(ChronoField.DAY_OF_YEAR, 2)
+     *    DD      2      appendValue(ChronoField.DAY_OF_YEAR, 2, 3, SignStyle.NOT_NEGATIVE)
      *    DDD     3      appendValue(ChronoField.DAY_OF_YEAR, 3)
      *    F       1      appendValue(ChronoField.ALIGNED_DAY_OF_WEEK_IN_MONTH)
      *    g..g    1..n   appendValue(JulianFields.MODIFIED_JULIAN_DAY, n, 19, SignStyle.NORMAL)
@@ -1838,8 +1838,8 @@
             case 'D':
                 if (count == 1) {
                     appendValue(field);
-                } else if (count <= 3) {
-                    appendValue(field, count);
+                } else if (count == 2 || count == 3) {
+                    appendValue(field, count, 3, SignStyle.NOT_NEGATIVE);
                 } else {
                     throw new IllegalArgumentException("Too many pattern letters: " + cur);
                 }
--- a/jdk/test/java/time/tck/java/time/format/TCKDateTimeFormatterBuilder.java	Sat May 07 08:44:48 2016 +0200
+++ b/jdk/test/java/time/tck/java/time/format/TCKDateTimeFormatterBuilder.java	Sun May 08 07:46:19 2016 +0000
@@ -794,6 +794,52 @@
         DateTimeFormatter df = new DateTimeFormatterBuilder().appendPattern("g").toFormatter();
          assertEquals(LocalDate.of(y, m, d).format(df), expected);
     }
+    //----------------------------------------------------------------------
+    @DataProvider(name="dayOfYearFieldValues")
+    Object[][] data_dayOfYearFieldValues() {
+        return new Object[][] {
+                {2016, 1, 1, "D", "1"},
+                {2016, 1, 31, "D", "31"},
+                {2016, 1, 1, "DD", "01"},
+                {2016, 1, 31, "DD", "31"},
+                {2016, 4, 9, "DD", "100"},
+                {2016, 1, 1, "DDD", "001"},
+                {2016, 1, 31, "DDD", "031"},
+                {2016, 4, 9, "DDD", "100"},
+        };
+    }
+
+    @Test(dataProvider="dayOfYearFieldValues")
+    public void test_dayOfYearFieldValues(int y, int m, int d, String pattern, String expected) throws Exception {
+        DateTimeFormatter df = new DateTimeFormatterBuilder().appendPattern(pattern).toFormatter();
+        assertEquals(LocalDate.of(y, m, d).format(df), expected);
+    }
+
+    @DataProvider(name="dayOfYearFieldAdjacentParsingValues")
+    Object[][] data_dayOfYearFieldAdjacentParsingValues() {
+        return new Object[][] {
+            {"20160281015", LocalDateTime.of(2016, 1, 28, 10, 15)},
+            {"20161001015", LocalDateTime.of(2016, 4, 9, 10, 15)},
+        };
+    }
+
+    @Test(dataProvider="dayOfYearFieldAdjacentParsingValues")
+    public void test_dayOfYearFieldAdjacentValueParsing(String input, LocalDateTime expected) {
+        DateTimeFormatter df = new DateTimeFormatterBuilder().appendPattern("yyyyDDDHHmm").toFormatter();
+        LocalDateTime actual = LocalDateTime.parse(input, df);
+        assertEquals(actual, expected);
+    }
+
+    @Test(expectedExceptions = DateTimeParseException.class)
+    public void test_dayOfYearFieldInvalidValue() {
+        DateTimeFormatter.ofPattern("DDD").parse("1234");
+    }
+
+    @Test(expectedExceptions = DateTimeParseException.class)
+    public void test_dayOfYearFieldInvalidAdacentValueParsingPattern() {
+        // patterns D and DD will not take part in adjacent value parsing
+        DateTimeFormatter.ofPattern("yyyyDDHHmmss").parse("201610123456");
+    }
 
     //-----------------------------------------------------------------------
     @DataProvider(name="secondsPattern")
--- a/jdk/test/java/time/test/java/time/format/TestDateTimeFormatterBuilder.java	Sat May 07 08:44:48 2016 +0200
+++ b/jdk/test/java/time/test/java/time/format/TestDateTimeFormatterBuilder.java	Sun May 08 07:46:19 2016 +0000
@@ -684,7 +684,7 @@
             {"LLLLL", "Text(MonthOfYear,NARROW_STANDALONE)"},
 
             {"D", "Value(DayOfYear)"},
-            {"DD", "Value(DayOfYear,2)"},
+            {"DD", "Value(DayOfYear,2,3,NOT_NEGATIVE)"},
             {"DDD", "Value(DayOfYear,3)"},
 
             {"d", "Value(DayOfMonth)"},
@@ -782,7 +782,7 @@
             {"xxxxx", "Offset(+HH:MM:ss,'+00:00')"},  // LDML
 
             {"ppH", "Pad(Value(HourOfDay),2)"},
-            {"pppDD", "Pad(Value(DayOfYear,2),3)"},
+            {"pppDD", "Pad(Value(DayOfYear,2,3,NOT_NEGATIVE),3)"},
 
             {"yyyy[-MM[-dd", "Value(YearOfEra,4,19,EXCEEDS_PAD)['-'Value(MonthOfYear,2)['-'Value(DayOfMonth,2)]]"},
             {"yyyy[-MM[-dd]]", "Value(YearOfEra,4,19,EXCEEDS_PAD)['-'Value(MonthOfYear,2)['-'Value(DayOfMonth,2)]]"},