The literal dash added to DateTimeFormatterBuilder causes the parsing to fail.

I am trying to create a DateTimeFormatter to fit the following example (it is actually a bit more complicated than that, but it should not matter).

 20180302-17:45:21 

I wrote the following, but this leads to an exception:

 new DateTimeFormatterBuilder() .append(DateTimeFormatter.BASIC_ISO_DATE) .appendLiteral('-') .append(DateTimeFormatter.ISO_LOCAL_TIME) .toFormatter() .parse("20180302-17:45:21"); 

The exception is:

 Exception in thread "main" java.time.format.DateTimeParseException: Text '20180302-17:45:21' could not be parsed at index 11 at java.base/java.time.format.DateTimeFormatter.parseResolved0(DateTimeFormatter.java:1988) at java.base/java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1816) 

The colon failure between 17:45 and DateTimeFormatterBuilder.appendLiteral does not seem to give any clues.

If I changed the literal to another character, say m , then it works fine:

 new DateTimeFormatterBuilder() .append(DateTimeFormatter.BASIC_ISO_DATE) .appendLiteral('m') .append(DateTimeFormatter.ISO_LOCAL_TIME) .toFormatter() .parse("20180302m17:45:21"); 

What's going on here? How to fix it if I can’t change the format?

Comments suggest that this is version dependent. I am using JDK 9.0.1, and was played back on 9.0.4 .

+8
java java-9 java-time
source share
1 answer

This is because DateTimeFormatter.BASIC_ISO_DATE contains an optional offset identifier. Apparently your formatter parses -17 as an offset, and then objects, because there is a colon in which the format requires a hyphen.

When you use m instead, it cannot be parsed as an offset and therefore matches the literal m in the format, and everything works.

I tried using the capital letter Z Z may also be an identifier for the offset.

 new DateTimeFormatterBuilder() .append(DateTimeFormatter.BASIC_ISO_DATE) .appendLiteral('Z') .append(DateTimeFormatter.ISO_LOCAL_TIME) .toFormatter() .parse("20180302Z17:45:21"); 

Now I got java.time.format.DateTimeParseException: Text '20180302Z17:45:21' could not be parsed at index 9 . Index 9 we immediately after Z , so it seems that the formatter is analyzing the offset, and then trying to find the literal Z , where 17 is located.

EDIT: And the solution? Instead of using BASIC_ISO_DATE add a template:

 .appendPattern("uuuuMMdd") 

Parsing now works on Java 9.0.4.

EDIT: Next, to illustrate the possibility of bias:

 System.out.println( LocalDate.now().format(DateTimeFormatter.BASIC_ISO_DATE) ); System.out.println( OffsetDateTime.now().format(DateTimeFormatter.BASIC_ISO_DATE) ); 

Printed

 20180305 20180305+0100 

So, in the first case, when the offset is not available, it simply does not work. In the second case, when it is available, it is also printed (without a colon).

An open question: why does it work in Java 8? Is this really a mistake?

Quote:

  • If the offset is not available for formatting or parsing, the format will be completed.
  • Displacement identifier without colons. If the offset has seconds, they will be processed, even if this does not apply to the ISO-8601 standard. Parsing the offset is soft, which allows you to use minutes and seconds - optional. The analysis is case insensitive.

From the documentation BASIC_ISO_DATE

+8
source share

All Articles