- 11 months ago 80
Java Question

DateTimeFormatter pattern with liternal and no separator does not work

The parser generated by

exhibits the following interesting behaviour which is preventing me from writing a pattern to parse a string like

System.out.println(DateTimeFormatter.ofPattern("yyyyMM").parse("201501", YearMonth::from)); // works
System.out.println(DateTimeFormatter.ofPattern("yyyyMM'aa'").parse("201501aa", YearMonth::from)); // works
System.out.println(DateTimeFormatter.ofPattern("yyyyMM'00'").parse("20150100", YearMonth::from));
// java.time.format.DateTimeParseException: Text '20150100' could not be parsed at index 0

I debuged the code, it seems the problem is caused by the year field parsing beyond the end of the string (max width for three y's and more is always 19). However, I don't understand how it could work for the pattern without the
literal at the end.

Is there any way to fix this withing having to use a formatter builder?


Since Jarrod below confirmed it's buggy, I did more googling and finally found the bug reports:

Both are only fixed in Java 9 though......

Answer Source

There is a bug in the DateTimePrinterParser:

I step debugged all the way through it, apparently you can not have digits as literals. Similar test codes proves this if you step debug all the way through to the DateTimeFormatterBuilder.parse() method you can see what it is doing wrong.

Apparently the Value(YearOfEra,4,19,EXCEEDS_PAD) parser consumes the 00 where they stop if those are not digits because it is looking for a number 4 to 19 digits long. The DateTimeFormatter that is embedded in the DateTimeParseContext is wrong.

Both of these fail:

final SimpleDateFormat sdf = new SimpleDateFormat("yyyyMM'00'");

Exception in thread "main" java.text.ParseException: Unparseable date: "20150100" at java.text.DateFormat.parse(

final DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyyMM'00'");
System.out.println(dateTimeFormatter.parse("20150100", YearMonth::from));

Exception in thread "main" java.time.format.DateTimeParseException: Text '20150100' could not be parsed at index 0 at java.time.format.DateTimeFormatter.parseResolved0( at java.time.format.DateTimeFormatter.parse(

Both of these succeed:

final SimpleDateFormat sdf = new SimpleDateFormat("yyyyMM'xx'");

Thu Jan 01 00:00:00 EST 2015

final DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyyMM'xx'");
System.out.println(dateTimeFormatter.parse("201501xx", YearMonth::from));


If you put a non-digit character literal like xx it works, digit literals don't.