JDK-8031085 : DateTimeFormatter won't parse dates with custom format "yyyyMMddHHmmssSSS"
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.time
  • Affected Version: 8
  • Priority: P3
  • Status: Resolved
  • Resolution: Fixed
  • OS: windows_8
  • Submitted: 2013-12-23
  • Updated: 2018-10-26
  • Resolved: 2016-04-25
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 9
9 b116Fixed
Related Reports
Duplicate :  
Duplicate :  
Duplicate :  
Duplicate :  
Duplicate :  
Relates :  
Relates :  
Description
FULL PRODUCT VERSION :
java version "1.8.0-ea"
Java(TM) SE Runtime Environment (build 1.8.0-ea-b120)
Java HotSpot(TM) 64-Bit Server VM (build 25.0-b62, mixed mode)


ADDITIONAL OS VERSION INFORMATION :
Windows 8.1

A DESCRIPTION OF THE PROBLEM :
Java 8 produces

java.time.format.DateTimeParseException: Text '20130812214600025' could not be parsed at index 0

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
run this with java 8

String x = "20130812214600025";
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyyMMddHHmmssSSS");
LocalDateTime t1 = LocalDateTime.parse(x, dtf);

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
parsed successfully
ACTUAL -
Exception in thread "main" java.time.format.DateTimeParseException: Text '20130812214600025' could not be parsed at index 0
at java.time.format.DateTimeFormatter.parseResolved0(DateTimeFormatter.java:1948)
at java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1850)
at java.time.LocalDateTime.parse(LocalDateTime.java:484)

REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
String x = "20130812214600025";
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyyMMddHHmmssSSS");
LocalDateTime t1 = LocalDateTime.parse(x, dtf);
---------- END SOURCE ----------
Comments
If the appendFraction() method is called in strict mode with width == maxWidth and decimalPoint == false then the code could use adjacent parsing mode. This would not be against the spec as the spec does not mention adjacent parsing in appendFraction(). However, implementing such a change would require a new inner class (subclass of NumberPrinterParser) in order to resolve the fraction. Given that users can just call appendValue() themselves it is not obvious that this is the right course of action wrt DTFBuilder. But if ofPattern() remains strict, then making the change described in this comment would make sense.
23-01-2014

Workaround: DateTimeFormatter dtf = new DateTimeFormatterBuilder().appendPattern("yyyyMMddHHmmss").appendValue(ChronoField.MILLI_OF_SECOND, 3).toFormatter() Adjacent value parsing is generally a hard problem. It is intended to handle the case where the first element is variable width (the year) and all other elements are fixed width (month, day etc). However, the "S" pattern letter is a fraction, not a value. Specifically, the fraction can be variable width - more or less than three digits are possible options. Given the general case of a variable width year and a variable width millisecond, it is not possible to determine which of the two fields was intended to be variable. Having said that, the implementation (and javadoc) have not ended up as I intended. The description of "fraction" in DateTimeFormatter describes actions in strict and lenient mode, but there is no way to access strict or lenient mode when using DateTimeFormatter.ofPattern(). This is a documentation bug that should be fixed by removing the discussion of strict vs lenient. Worse however is that the SSS pattern has therefore ended up using strict mode when lenient mode would be appropriate. As it currently stands, DateTimeFormatter.ofPattern("hhmmss.SSS") requires three digits for milliseconds, when it was originally intended to require 0 to 9 (the lenient behaviour). I tried changing the whole of the DateTimeFormatter.ofPattern() method to use lenient parsing, and it broke no tests (which is bad in its own way). This might be a valid fix, but only if included in JDK 8, as once people adapt to the strict parsing it will be hard to make it lenient. Given that the current implementation requires three digits for SSS, it is thus very surprising that adjacent value parsing does not apply.
19-01-2014

A possible workaround is to use the pattern lettern "n", for NANO_OF_SECOND or explicitly use the DateTimeFormatBuilder to do the equivalent - appendValue(ChronoField.NANO_OF_SECOND, n).
09-01-2014

Release team: Approved for deferral. We're putting this on 9 for now. You can backport it to 8u if needed.
07-01-2014

As currently specified and implemented Fractions do not participate in the protocol for adjacent value parsing. The fraction digits are included in the digits available for parsing the year, month, day, etc. The excess digits cause the parsing of the year to terminate with an parsing error. Adding an explicit decimal point (".") before the fraction in both the pattern and the data allows the parse to succeed.
07-01-2014

Attached test class.
30-12-2013