JDK8: unable to parse LocalTime

19.2k views Asked by At

I managed to parse a String to a LocalDate object:

DateTimeFormatter f1=DateTimeFormatter.ofPattern("dd MM yyyy");
LocalDate d=LocalDate.parse("26 08 1984",f1);
System.out.println(d); //prints "1984-08-26"

But I cannot do the same with LocalTime. This piece of code:

DateTimeFormatter f2=DateTimeFormatter.ofPattern("hh mm");
LocalTime t=LocalTime.parse("11 08",f2); //exception here
System.out.println(t);

Throws a DateTimeParseException:

Exception in thread "main" java.time.format.DateTimeParseException: Text '11 08' could not be parsed: Unable to obtain LocalTime from TemporalAccessor: {MinuteOfHour=8, HourOfAmPm=11},ISO of type java.time.format.Parsed
    at java.time.format.DateTimeFormatter.createError(Unknown Source)
    at java.time.format.DateTimeFormatter.parse(Unknown Source)
    at java.time.LocalTime.parse(Unknown Source)
    at com.mui.cert.Main.<init>(Main.java:21)
    at com.mui.cert.Main.main(Main.java:12)
Caused by: java.time.DateTimeException: Unable to obtain LocalTime from TemporalAccessor: {MinuteOfHour=8, HourOfAmPm=11},ISO of type java.time.format.Parsed
    at java.time.LocalTime.from(Unknown Source)
    at java.time.LocalTime$$Lambda$15/1854731462.queryFrom(Unknown Source)
    at java.time.format.Parsed.query(Unknown Source)
    ... 4 more

What am I doing wrong?

4

There are 4 answers

2
Jordi Castilla On BEST ANSWER

If you use a specific format, according to API:

The string must represent a valid time and is parsed using DateTimeFormatter.ISO_LOCAL_TIME.

hh mm 

for 24h must be

HH mm

or for 12h

kk mm

The handled formats must have this conditions:

  • Two digits for the hour-of-day. This is pre-padded by zero to ensure two digits.
  • A colon
  • Two digits for the minute-of-hour. This is pre-padded by zero to ensure two digits.
  • If the second-of-minute is not available then the format is complete.
  • A colon
  • Two digits for the second-of-minute. This is pre-padded by zero to ensure two digits.
  • If the nano-of-second is zero or not available then the format is complete.
  • A decimal point
  • One to nine digits for the nano-of-second. As many digits will be output as required.
0
Alex Taylor On

In this case Unable to obtain LocalTime from TemporalAccessor means it cannot determine the how far through the day the given string represents i.e. there is not enough information to construct a LocalTime. Behind the scenes, the code looks something like this expanded Java 8 version (which gives a similar error):

DateTimeFormatter f2 = DateTimeFormatter.ofPattern("hh mm");
TemporalAccessor temporalAccessor = f2.parse("11 08");
LocalTime t = temporalAccessor.query(LocalTime::from);
System.out.println(t);

The LocalTime::from documentation says

The conversion uses the TemporalQueries.localTime() query, which relies on extracting the NANO_OF_DAY field.

Your error is telling you that the TemporalAccessor only has two fields, neither of which is a NANO_OF_DAY field. The minimum allowable patterns for retrieving a LocalTime using a DateTimeFormatter are:

DateTimeFormatter.ofPattern("ha");
DateTimeFormatter.ofPattern("Ka");
DateTimeFormatter.ofPattern("ah");
DateTimeFormatter.ofPattern("aK");
DateTimeFormatter.ofPattern("k");
DateTimeFormatter.ofPattern("H");

Your pattern must contain at least one of those strings to get a NANO_OF_DAY field in the internal TemporalAccessor from which a LocalTime can be constructed.

2
dogant On

You need to use capital HH in the pattern

DateTimeFormatter f2=DateTimeFormatter.ofPattern("HH mm");

or do this, for clock-hour-of-am-pm you need to specify it.

This should also work

DateTimeFormatter f2=DateTimeFormatter.ofPattern("hh mm a");
LocalTime t=LocalTime.parse("11 08 AM",f2); //exception here
0
walkeros On

Use DateTimeFormatter.ofPattern("kk mm"); for 12 hour clock or DateTimeFormatter.ofPattern("HH mm") for 24 hour clock

If you want to parse time with hh you must combine it wih a where you define AM or PM:

DateTimeFormatter f2 = DateTimeFormatter.ofPattern("hh mm a");
LocalTime t = LocalTime.parse("11 08 AM", f2);