Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to handle upper or lower case in JSR 310? [duplicate]

If a month is in UPPER or lower case, i.e. not Title case, DateTimeFormatter cannot parse the date. Is there a simple way to convert a date to title case, or a way to make the formatter more lenient?

for (String date : "15-JAN-12, 15-Jan-12, 15-jan-12, 15-01-12".split(", ")) {
    try {
        System.out.println(date + " => " + LocalDate.parse(date,
                                     DateTimeFormatter.ofPattern("yy-MMM-dd")));
    } catch (Exception e) {
        System.out.println(date + " => " + e);
    }
}

prints

15-JAN-12 => java.time.format.DateTimeParseException: Text '15-JAN-12' could not be parsed at index 3
15-Jan-12 => 2015-01-12
15-01-12 => java.time.format.DateTimeParseException: Text '15-01-12' could not be parsed at index 3
15-jan-12 => java.time.format.DateTimeParseException: Text '15-jan-12' could not be parsed at index 3
like image 685
Peter Lawrey Avatar asked Feb 04 '15 09:02

Peter Lawrey


1 Answers

DateTimeFormatters are strict and case sensitive by default. Use a DateTimeFormatterBuilder and specify parseCaseInsensitive() to parse case insensitive.

DateTimeFormatter formatter = new DateTimeFormatterBuilder()
    .parseCaseInsensitive()
    .appendPattern("yy-MMM-dd")
    .toFormatter(Locale.US);

To be able to parse numeric months (ie. "15-01-12"), you also need to specify parseLenient().

DateTimeFormatter formatter = new DateTimeFormatterBuilder()
    .parseCaseInsensitive()
    .parseLenient()
    .appendPattern("yy-MMM-dd")
    .toFormatter(Locale.US);

You can also be more verbose to specify only the month part as case insensitive/lenient:

DateTimeFormatter formatter = new DateTimeFormatterBuilder()
    .appendPattern("yy-")
    .parseCaseInsensitive()
    .parseLenient()
    .appendPattern("MMM")
    .parseStrict()
    .parseCaseSensitive()
    .appendPattern("-dd")
    .toFormatter(Locale.US);

In theory, this could be faster, but I'm not sure if it is.

PS: If you specify parseLenient() before the year part, it will also parse 4 digit years (ie. "2015-JAN-12") correctly.

like image 81
Harald K Avatar answered Sep 29 '22 10:09

Harald K