Java 8 DateTimeFormatter two digit year 18 parsed to 0018 instead of 2018?

There is not a single string of y or u that will allow you to parse both two and four digit years. However, you may use optional parts in the format pattern string to specify that a two or four digit year may be present:

public static LocalDate parseDateString(CharSequence date) {
    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("M/d/[uuuu][uu]");
    return LocalDate.parse(date, formatter);
}

Try it:

    System.out.println(parseDateString("01/05/18"));
    System.out.println(parseDateString("01/06/2018"));

This printed:

2018-01-05
2018-01-06

In the format pattern string you need to put the four digit year first. With the opposite order, when trying to parse a four digit year, the formatter will parse two digits, decide it was successful this far, and then complain about unparsed text after the two digits.

If you want more precise control over how two digit years are interpreted:

    DateTimeFormatter formatter = new DateTimeFormatterBuilder().appendPattern("M/d/")
            .optionalStart()
            .appendPattern("uuuu")
            .optionalEnd()
            .optionalStart()
            .appendValueReduced(ChronoField.YEAR, 2, 2, 1920)
            .optionalEnd()
            .toFormatter();

Using this formatter in the above method let’s try:

    System.out.println(parseDateString("01/05/22"));

This prints:

1922-01-05

Giving 1920 as base (as in my example code) will cause two digit years to end up in the interval from 1920 through 2019. Adjust the value to your requirements.