When I try to run the following code:
LocalTime test = LocalTime.parse("8:00am", DateTimeFormatter.ofPattern("hh:mma"));
I get this:
Exception in thread "main" java.time.format.DateTimeParseException: Text '8:00am' could not be parsed at index 0
Any idea why this might be happening?
AM/PM are uppercase, and you need to use
h
to specify one digit for hours (withhh
two digits are required). Like,The AM/PM tokens have* to be uppercase:
Patterns definitions for hours:
Refer to the
DateTimeFormatter
javadocs for all available patterns: https://docs.oracle.com/javase/8/docs/api/java/time/format/DateTimeFormatter.html-- EDIT
*As per @Hugo's comment, this is related to the Locale your formatter is setup on. If you are not specifying any, then the JVMs default is used. It just happens that the vast majority of Locales enforces AM/PM tokens to be upper case:
AM/PM
pattern is locale sensitive. If you create a formatter and don't set ajava.util.Locale
, it'll use the JVM's default. Anyway, I've checked in JDK 1.8.0_144 and there's no locale that uses lowercaseam
as the text forAM/PM
field (I've found locales that usea.m.
andAM
, but noam
).So, one alternative is to set a locale that uses
AM
(example:Locale.ENGLISH
) and use ajava.time.format.DateTimeFormatterBuilder
to build a case insensitive formatter. Another detail is that the hour in the input has only 1 digit, so you must change the pattern toh
(which accepts 1 or 2 digits, whilehh
accepts only 2):The problem is that the locale can also affect other fields (if you use month or day of week names, or week based fields, for example).
Another detail is that the formatter is case insensitive only for parsing. When formatting, it'll use the locale specific symbols, which in this case is uppercase. So this:
Prints:
To not depend on the locale, you can use a map of custom texts for this field, using a
java.time.temporal.ChronoField
:The difference from the previous formatter is that it uses the custom text (lowercase
am
andpm
) for both parsing and formatting. So this code:Will print:
You need to capitalize to AM and add a leading zero in front of the 8.