Inconsistent Behaviour in Java LocalDate parse

Viewed 114

I need to parse a date which will be in the format dd/MM/yyyy when I parse an invalid date "29/02/2007", it return back to me as a LocalDate 2007-02-28, code as follows:

        LocalDate birthD = null;
    
    try {
        birthD = LocalDate.parse("29/02/2007", DateTimeFormatter.ofPattern("dd/MM/yyyy"));
    } catch (DateTimeParseException e) {
        e.printStackTrace();
    }


    System.out.println("birthDStr: " + birthDStr);
    System.out.println("parsed birthD: " + birthD);

However, if I parse using the ISO format (without the DateTimeFormatter), then it gives exception, code as follows:

        final String birthDStr = "2007-02-29";
    LocalDate birthD = null;
    
    try {
        birthD = LocalDate.parse(birthDStr);
    } catch (DateTimeParseException e) {
        e.printStackTrace();
    }


    System.out.println("birthDStr: " + birthDStr);
    System.out.println("parsed birthD: " + birthD);

Exception:

java.time.format.DateTimeParseException: Text '2007-02-29' could not be parsed: Invalid date 'February 29' as '2007' is not a leap year
at java.time.format.DateTimeFormatter.createError(DateTimeFormatter.java:1920)
at java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1855)
at java.time.LocalDate.parse(LocalDate.java:400)
at java.time.LocalDate.parse(LocalDate.java:385)
at com.cchaidoris.quick_test.DateTest.parseTest2(DateTest.java:65)
at com.cchaidoris.quick_test.DateTest.main(DateTest.java:41)
Caused by: java.time.DateTimeException: Invalid date 'February 29' as '2007' is not a leap year
    at java.time.LocalDate.create(LocalDate.java:429)
    at java.time.LocalDate.of(LocalDate.java:269)
    at java.time.chrono.IsoChronology.resolveYMD(IsoChronology.java:560)
    at java.time.chrono.IsoChronology.resolveYMD(IsoChronology.java:123)
    at java.time.chrono.AbstractChronology.resolveDate(AbstractChronology.java:472)
    at java.time.chrono.IsoChronology.resolveDate(IsoChronology.java:492)
    at java.time.chrono.IsoChronology.resolveDate(IsoChronology.java:123)
    at java.time.format.Parsed.resolveDateFields(Parsed.java:351)
    at java.time.format.Parsed.resolveFields(Parsed.java:257)
    at java.time.format.Parsed.resolve(Parsed.java:244)
    at java.time.format.DateTimeParseContext.toResolved(DateTimeParseContext.java:331)
    at java.time.format.DateTimeFormatter.parseResolved0(DateTimeFormatter.java:1955)
    at java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1851)

So my question is, I want to regard this:

LocalDate.parse("29/02/2007", DateTimeFormatter.ofPattern("dd/MM/yyyy"));
 

as invalid, how can I do using LocalDate.parse?

2 Answers

You need to change the resolver style:

DateTimeFormatter formatter = DateTimeFormatter
    .ofPattern("dd/MM/uuuu")
    .withResolverStyle(ResolverStyle.STRICT);
LocalDate.parse("29/02/2007", formatter); // Throws

Note the use of uuuu instead of yyyy, to specify the year instead of year-of-era. (I'm sure there's some way of getting yyyy to work and assume an era of AD, but I'm not sure how off-hand.)

Note that LocalDate.parse (without a formatter) is documented to use DateTimeFormatter.ISO_LOCAL_DATE which uses the STRICT resolver - so there isn't really an inconsistency here.

Use this for tests.

@Test
void test() {

    final String birthDStr = "2007-02-27";
    LocalDate birthD = null;

    try {
        birthD = LocalDate.parse(birthDStr);
    } catch (DateTimeParseException e) {
        e.printStackTrace();
    }

}


@Test
void test() {

    final String birthDStr = "29/02/2007";
    LocalDate birthD = null;
    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("d/MM/yyyy");

    try {
        birthD = LocalDate.parse(birthDStr, formatter);
    } catch (DateTimeParseException e) {
        e.printStackTrace();
    }

}

Your code correct, not correct date. Text '2007-02-29' could not be parsed: Invalid date 'February 29' as '2007' is not a leap year.

Related