Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

DateTimeFormatter in Java 11 (Zulu) does not work for formats with AM / PM

I am trying to convert a String representing a time in AM/PM format to java.sql.Time, but I get a DateTimeParseException:

public static java.sql.Time getTimeValue(String valStr) {
    if (valStr == null || valStr.isEmpty()) {
        return null;
    }
    DateTimeFormatter dateTimeFormatter;
    if (valStr.toUpperCase().endsWith("AM") || valStr.toUpperCase().endsWith("PM")) {
        dateTimeFormatter = DateTimeFormatter.ofPattern("h:mm a");
    } else {
        dateTimeFormatter = DateTimeFormatter.ofPattern("HH:mm");
    }
    try {
        return java.sql.Time.valueOf(LocalTime.parse(valStr, dateTimeFormatter));
    } catch (Exception ex) {
        return null;
    }
}

For an input value of "7:16 PM" I get the following exception:

java.time.format.DateTimeParseException: Text '7:16 PM' could not be parsed at index 5
at java.base/java.time.format.DateTimeFormatter.parseResolved0(DateTimeFormatter.java:2046)
at java.base/java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1948)
at java.base/java.time.LocalTime.parse(LocalTime.java:463)
at ...getTimeValue(....java:864)

I am using Java 11.0.5, Zulu 11.35.15 for 64-bits.

Does anyone have any idea on why this isn't working? I have no problems with the same piece of code in Java 8.

I have checked the value of the DateTimeFormatter and it is the one corresponding to the "h:mm a" pattern.

like image 1000
Andrei Roșu-Cojocaru Avatar asked Oct 29 '25 21:10

Andrei Roșu-Cojocaru


1 Answers

Thanks a lot John Skeet and Robert, indeed, it was a Locale problem.

  • In my minimal example, everything worked as expected, but that was because I had US Locale.
  • In the production code, the Locale were from German where it seems that AM/PM does not exist at all. The format of the date came from an external device which was exporting the information into our application.

The solution was to always create the DateTimeFormatter with the Locale.US argument, so everything works as expected now.

if (valStr.toUpperCase().endsWith("AM") || valStr.toUpperCase().endsWith("PM")) {
  dateTimeFormatter = DateTimeFormatter.ofPattern("h:mm a", Locale.US);
} else {
  dateTimeFormatter = DateTimeFormatter.ofPattern("HH:mm");
}
like image 106
Andrei Roșu-Cojocaru Avatar answered Nov 01 '25 12:11

Andrei Roșu-Cojocaru



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!