How to parse time in any format with LocalTime.parse?

Viewed 6256

I am having trouble using java's LocalTime to parse a string with hours, minutes, and seconds.

LocalTime t = LocalTime.parse("8:30:17"); // Simplification

This throws the following exception:

Exception in thread "main" java.time.format.DateTimeParseException: Text '8:30:17' could not be parsed at index 0

5 Answers

The default formatter expects an ISO format, which uses 2 digits for each of the hours, minutes and seconds.

If you want to parse the time you showed, which only has one digit for hours, you will need to provide a custom formatter (note the single H):

DateTimeFormatter formatter = DateTimeFormatter.ofPattern("H:mm:ss");
LocalTime t = LocalTime.parse(times.get(i), formatter);

You'll need to pass in a custom DateTimeFormatter like this:

DateTimeFormatter formatter = DateTimeFormatter.ofPattern("H:mm:ss");
LocalTime t = LocalTime.parse(times.get(i), formatter);

Take a look at the docs, as the letters you need to use might be different.

You need to use DateTimeFormatter to give parser a format pattern to parse.

DateTimeFormatter formatter =DateTimeFormatter.ofPattern("H:mm:ss");
LocalTime t = LocalTime.parse(times.get(i), formatter);

Format Pattern Letters:

H       hour-of-day (0-23)
m       minute-of-hour
s       second-of-minute            
h       clock-hour-of-am-pm (1-12)

From LocalTime.parse documentation :

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

According to the ISO_LOCAL_TIME documentation the condition for the hours is this:

Two digits for the hour-of-day. This is pre-padded by zero to ensure two digits.

You are parsing the value 8:30:17, one digit instead of two digits and so you are breaking the condition, causing the error.

By default, LocalTime#parse parses the input string using DateTimeFormatter.ISO_LOCAL_TIME whose format consists of:

  • 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.

Since your input string is not in this format, you have encountered the exception. You can get around the exception by using a DateTimeFormatter which allows you to specify a custom format. You can use H:m:s as the format.

Demo:

import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.Locale;

public class Main {
    public static void main(String[] args) {
        DateTimeFormatter dtf = DateTimeFormatter.ofPattern("H:m:s", Locale.ENGLISH);
        LocalTime t = LocalTime.parse("8:30:17", dtf);
        System.out.println(t);
    }
}

Output:

08:30:17

ONLINE DEMO

Note that for formatting, the single letter, H works for single as well as a two-digit hour. Similar is the case with m and s as well.

Another thing you should always keep in mind is that the Date-Time formatting types are Locale-sensitive and therefore you should always specify the applicable Locale when using them. Check Never use SimpleDateFormat or DateTimeFormatter without a Locale to learn more about it.

Learn more about the modern Date-Time API* from Trail: Date Time.


* If you are working for an Android project and your Android API level is still not compliant with Java-8, check Java 8+ APIs available through desugaring. Note that Android 8.0 Oreo already provides support for java.time.

Related