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
--- 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)]]"},