Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

LocalDateTime.parse() with a pattern only numbers [duplicate]

I want to parse a LocalDateTime from the following pattern:

yyyyMMddHHmmss000000

That means the usual "yyyy...ss" and then six trailing zeros.

So, formatting works fine:

String p = "yyyyMMddHHmmss'000000'";
LocalDateTime.now().format(DateTimeFormatter.ofPattern(p));

and but parsing:

String p, v;
p = "yyyyMMddHHmmss";                                    // without '000000'
v = "20160131235930";
LocalDateTime.parse(v, DateTimeFormatter.ofPattern(p));  // it works


p = "yyyy-MMddHHmmss'000000'";                           // with '-' in between
v = "2016-0131235930000000";
LocalDateTime.parse(v, DateTimeFormatter.ofPattern(p));  // it works


p = "yyyyMMddHHmmss'000000'";                            // with '000000' but without '-'
v = "20160131235930000000";
LocalDateTime.parse(v, DateTimeFormatter.ofPattern(p));  // it throws Exception

The Exception:

java.time.format.DateTimeParseException: Text '20160131235930000000' could not be parsed at index 0
at java.time.format.DateTimeFormatter.parseResolved0(DateTimeFormatter.java:1947)
at java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1849)
at java.time.LocalDateTime.parse(LocalDateTime.java:492)
...

I can't change the format of the input value. How can I parse it correctly? Is my pattern wrong?

Java Version: 1.8.0_60 on OSX

like image 871
Marcel Avatar asked Mar 18 '16 13:03

Marcel


1 Answers

This looks like it is a bug with DateTimeFormatter and its handling of variable width input.

Constructing the following formatter with DateTimeFormatterBuilder solves the problem

DateTimeFormatter formatter = 
        new DateTimeFormatterBuilder().appendValue(ChronoField.YEAR, 4)
                                      .appendValue(ChronoField.MONTH_OF_YEAR, 2)
                                      .appendValue(ChronoField.DAY_OF_MONTH, 2)
                                      .appendValue(ChronoField.HOUR_OF_DAY, 2)
                                      .appendValue(ChronoField.MINUTE_OF_HOUR, 2)
                                      .appendValue(ChronoField.SECOND_OF_MINUTE, 2)
                                      .appendLiteral("000000")
                                      .toFormatter();

The difference is that it forces a width for the field to parse with appendValue(field, width).

This bug sounds similar to the one mentioned in another answer of mine although it mentions milliseconds instead of literal characters in the pattern.

like image 184
Tunaki Avatar answered Oct 20 '22 00:10

Tunaki