Java: How to convert a string (HH:MM:SS) to a duration?

tl;dr

No need to define your own Duration class, as Java provides one.

Duration.between (                  // Represent a span of time of hours, minutes, seconds. 
    LocalTime.MIN ,                 // 00:00:00
    LocalTime.parse ( "08:30:00" )  // Parse text as a time-of-day. 
)                                   // Returns a `Duration` object, a span-of-time. 
.toString()                         // Generate a `String` with text in standard ISO 8601 format. 

PT8H30M

And parse standard ISO 8601 formatted text.

Duration.parse( "PT8H30M" )   // Parse standard ISO 8601 text yo get a `Duration` object. 

Table of span-of-time classes in Java and in the ThreeTen-Extra project


Avoid HH:MM:SS format

If by the string 08:30:00 you mean “eight and a half hours” span of time rather than a time-of-day “half-past eight in the morning”, then avoid that format of HH:MM:SS. That format ambiguous, appearing to be a time-of-day. Instead use the standard ISO 8601 format discussed below.

Duration and time-of-day are two very different concepts. You must be clear on them, each should be distinct in your mind. Using the ambiguous format of HH:MM:SS makes that distinction all the more difficult (so avoid that format!).

java.time

The modern way is with the java.time classes.

LocalTime

First parse your string as a LocalTime. This class represents a time-of-day without a date and without a time zone. Having no time zone means these objects are based on a generic 24-hour clock without regard for anomalies such as Daylight Saving Time (DST).

We do not really want a LocalTime as your input string represents a span of time rather than a time-of-day. But this is just the first step.

LocalTime lt = LocalTime.parse ( "08:30:00" );

Duration

To represent the desired span-of-time, we want the Duration class. This class is for spans of time not attached to the timeline. We can create one by converting that LocalTime via getting the amount of time from the beginning of the time-of-day clock, 00:00:00.0 or LocalTime.MIN, and the lt we just instantiated.

Duration d = Duration.between ( LocalTime.MIN , lt );

Editing the input string

The approach above using LocalTime only works if your input strings represent a duration of less than 24 hours. If over 24 hours, you will parse the input string yourself.

Something like the following code. Of course the actual parsing depends on resolving the ambiguity of your particular input string. Is 50:00 meant to be fifty hours or fifty minutes? (This ambiguity is a strong reason to avoid this confusing format whenever possible, and stick with ISO 8601 formats.)

String input = "50:00";  // Or "50:00:00" (fifty hours, either way)

String[] parts = input.split ( ":" );
Duration d = Duration.ZERO;
if ( parts.length == 3 ) {
    int hours = Integer.parseInt ( parts[ 0 ] );
    int minutes = Integer.parseInt ( parts[ 1 ] );
    int seconds = Integer.parseInt ( parts[ 2 ] );
    d = d.plusHours ( hours ).plusMinutes ( minutes ).plusSeconds ( seconds );
} else if ( parts.length == 2 ) {
    int hours = Integer.parseInt ( parts[ 0 ] );
    int minutes = Integer.parseInt ( parts[ 1 ] );
    d = d.plusHours ( hours ).plusMinutes ( minutes );
} else {
    System.out.println ( "ERROR - Unexpected input." );
}

ISO 8601

We can see the result by generating a String in standard ISO 8601 format for durations by simply calling Duration::toString. The java.time classes use ISO 8601 by default when parsing/generating strings. For durations, the standard format is PnYnMnDTnHnMnS where the P marks the beginning and the T separates the years-months-days portion from the hours-minutes-seconds portion. So, our eight-and-a-half hours will appear as PT8H30M.

System.out.println ( “d.toString(): ” + d );

d.toString(): PT8H30M

Collecting Duration objects

You can make a List holding elements of the type Duration.

List<Duration> durations = new ArrayList<>( 3 );  // Initial capacity of 3 elements.
durations.add( d ) ;
durations.add( Duration.between ( LocalTime.MIN , LocalTime.parse ( "03:00:00" ) ) ) ;
durations.add( Duration.between ( LocalTime.MIN , LocalTime.parse ( "01:15:00" ) ) ) ;

durations.toString(): [PT8H30M, PT3H, PT1H15M]

Remember that the strings you see in that output like PT8H30M are just that: output of generated strings. The Duration type is not a simple string but rather generates a String object by its toString method.

If you stick to the ISO 8601 formats, you can easily parse as well as generate such strings. No need to go through the LocalTime conversion rigamarole we performed at the top of this Answer.

Duration d = Duration.parse( "PT8H30M" );

See this example code live in IdeOne.com.


About java.time

The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.

The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.

To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.

Where to obtain the java.time classes?

The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.

Leave a Comment