5

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

Ole V.V.
  • 81,772
  • 15
  • 137
  • 161
Yury
  • 69
  • 1
  • 7

5 Answers5

6

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.

cegredev
  • 1,485
  • 2
  • 11
  • 25
6

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);
assylias
  • 321,522
  • 82
  • 660
  • 783
  • Won't this break when it is, say, 10 o'clock? – cegredev Apr 11 '20 at 15:30
  • 2
    No it won't (see the javadoc: "*If the count of letters is one, then the value is output using the minimum number of digits and without padding.*"). – assylias Apr 11 '20 at 15:34
  • Just tested it. Hey @Yuri, make this the accepted answer again, it's the correct one. – cegredev Apr 11 '20 at 15:35
  • 1
    It’s a bit funny but very useful, @Schred: For numbers (including hour of day) one pattern letter does not mean one digit but rather *as many digits as it takes*. So it will parse `8`, `08` and `10` happily. And print `8` or `10` (never `08`). – Ole V.V. Apr 12 '20 at 05:22
1

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)
Eklavya
  • 17,618
  • 4
  • 28
  • 57
  • @OleV.V. The interesting part is it the answer is accepted when it is `HH:mm:ss` this format. Check the edit history. – Eklavya Apr 12 '20 at 10:54
1

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.

dariosicily
  • 4,239
  • 2
  • 11
  • 17
0

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.

Arvind Kumar Avinash
  • 71,965
  • 6
  • 74
  • 110