3

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.

Naman
  • 27,789
  • 26
  • 218
  • 353
  • Stimate domn Roșu-Cojocaru, position 5 is the P from PM. It appears that you will need to either avoid AM/PM and replace 7:16 PM into 19:16, or to somehow tell the pattern. Maybe h:mm a is incorrect. – Lajos Arpad Dec 18 '19 at 17:32
  • I figured out that much myself, thank you very much. Pattern "h:mm a" should be correct. The "h:mm" should have no problems, since it did not throw any errors at those positions while "a" is, according to the documentation, "am-pm-of-day" (e.g. PM) - https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/time/format/DateTimeFormatter.html. – Andrei Roșu-Cojocaru Dec 18 '19 at 17:36
  • 7
    What's your system locale? A number of the operations you're doing here are dependent on the system locale. If you could provide a [mcve] for us to easily copy/compile/run, that would make it easier to help you - along with that locale information. – Jon Skeet Dec 18 '19 at 17:42
  • 1
    Doies https://stackoverflow.com/questions/57615971/java-simpledateformat-throwing-parseexception-unparseable-date-on-windows-but-n/57616212#57616212 help? – Robert Dec 18 '19 at 17:52

1 Answers1

2

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");
}
  • 4
    Note that `toUpperCase()` is also Locale-specific. It would probably be better to specify `Locale.US` to that too. – Jon Skeet Dec 18 '19 at 18:33