Java 8 DateTimeFormatterBuilder().appendOptional not working

My requirement is to validate that a date String is in the correct format based on a set of valid formats specified.

Valid formats:

MM/dd/yy
MM/dd/yyyy

I created a simple test method that uses the Java 8 DateTimeFormatterBuilder to create a flexible formatter that supports multiple optional formats. Here is the code:

public static void test() {
    DateTimeFormatter formatter = new DateTimeFormatterBuilder()
            .appendOptional(DateTimeFormatter.ofPattern("MM/dd/yy"))
            .appendOptional(DateTimeFormatter.ofPattern("MM/dd/yyyy"))
            .toFormatter();

    String dateString = "10/30/2017";

    try {
        LocalDate.parse(dateString, formatter);
        System.out.println(dateString + " has a valid date format");
    } catch (Exception e) {
        System.out.println(dateString + " has an invalid date format");
    }
}

When I run this, here is the output

10/30/2017 has an invalid date format

As you see in the code, the valid date formats are MM/dd/yy and MM/dd/yyyy. My expectation was that the date 10/30/2017 should be valid as it matches MM/dd/yyyy. However, 10/30/2017 is being reported as invalid.

What is going wrong ? Why is this not working ?

I also tried

.appendOptional(DateTimeFormatter.ofPattern("MM/dd/yy[yy]"))

in place of

.appendOptional(DateTimeFormatter.ofPattern("MM/dd/yy"))
.appendOptional(DateTimeFormatter.ofPattern("MM/dd/yyyy"))

but still had the same issue.

This code runs as expected if I use:

String dateString = "10/30/17";

in place of

String dateString = "10/30/2017";

I have 2 questions

  1. What is going wrong here ? Why is it not working for "10/30/2017" ?

  2. Using Java 8, how to correctly create a flexible Date formatter (a formatter that supports multiple optional formats) ? I know the use of [] to create optional sections in the pattern string itself. I'm looking for something more similar to what I am trying (avoiding [] inside the pattern string and using separate optional clauses for each separate format string)

Jon Skeet
people
quotationmark

I suspect what's happening is that your shorter format is parsing the first two digits, but then failing because there's some left over data. If you use the longer format first, it appears to work:

DateTimeFormatter formatter = new DateTimeFormatterBuilder()
    .appendOptional(DateTimeFormatter.ofPattern("MM/dd/yyyy"))
    .appendOptional(DateTimeFormatter.ofPattern("MM/dd/yy"))
    .toFormatter();

That works for me with both "10/30/17" and "10/30/2017".

people

See more on this question at Stackoverflow