Conversion of hours, min, sec. Line by hour
I want to convert time in the following format to hours.
My input, which is a temporary format, might look like
1 hour 30 mins 20 secs
2 hrs 10 mins
45 mins
whereas my output would be:
1.505
2.167
0.75
This is a clock.
I am currently doing this manually by parsing the input string 1 hour 30 mins 20 secs
, detecting if a word is present hour/hours/hrs/hr
, and then taking the previous digits - same for minutes and seconds. I am using a formula to convert minutes and seconds to hours manually.
Is there a built-in condition I can use in Java?
source to share
An alternative way would be to parse it as aDuration
, but first you need to change the format a bit. Something like:
String adjusted = input.replaceAll("\\s+(hour|hr)[s]\\s+", "H");
//Do the same for minutes and seconds
//So adjusted looks like 1H30M20S
Duration d = Duration.parse("PT" + adjusted);
double result = d.toMillis() / 3_600_000d;
source to share
Normally I would not recommend Joda-Time (as it has been superseded by new Java APIs), but it is the only API I know with good formatting / parser for periods.
You can use a class PeriodFormatterBuilder
and use a method appendSuffix
to define suffixes for singular and multiple values ββfor each field:
import org.joda.time.Period;
import org.joda.time.format.PeriodFormatter;
import org.joda.time.format.PeriodFormatterBuilder;
// method to parse the period
public void getPeriod(String input) {
PeriodFormatter formatter = new PeriodFormatterBuilder()
// hours (singular and plural suffixes)
.appendHours().appendSuffix("hour", "hours")
// minutes
.appendMinutes().appendSuffix("min", "mins")
// seconds
.appendSeconds().appendSuffix("sec", "secs")
// create formatter
.toFormatter();
// remove spaces and change "hr" to "hour"
Period p = formatter.parsePeriod(input.replaceAll(" ", "").replaceAll("hr", "hour"));
double hours = p.getHours();
hours += p.getMinutes() / 60d;
hours += p.getSeconds() / 3600d;
System.out.println(hours);
}
// tests
getPeriod("1 hour 30 mins 20 secs");
getPeriod("2 hrs 10 mins");
getPeriod("45 mins");
Output:
+1.5055555555555555
2.1666666666666665
0.75
Another way to create it PeriodFormatter
is appendSuffix
with regular expressions. This is useful when you have many different options for the suffix (for example, hour
and hr
for the field hours):
PeriodFormatter formatter = new PeriodFormatterBuilder()
// hours (all possible suffixes for singular and plural)
.appendHours()
.appendSuffix(
// regular expressions for singular and plural
new String[] { "^1$", ".*", "^1$", ".*" },
// possible suffixes for singular and plural
new String[] { " hour", " hours", " hr", " hrs" })
// optional space (if there are more fields)
.appendSeparatorIfFieldsBefore(" ")
// minutes
.appendMinutes().appendSuffix(" min", " mins")
// optional space (if there are more fields)
.appendSeparatorIfFieldsBefore(" ")
// seconds
.appendSeconds().appendSuffix(" sec", " secs")
// create formatter
.toFormatter();
Note that I also added appendSeparatorIfFieldsBefore(" ")
to indicate that it has a space before the next field.
The good thing about this version is that you don't need to preprocess the input:
// no need to call replaceAll (take input just as it is)
Period p = formatter.parsePeriod(input);
The output is the same as above.
Java 8 API with date
As @assylian's answer pointed out , you can use the class java.time.Duration
:
public void getDuration(String input) {
// replace hour/min/secs strings for H, M and S
String adjusted = input.replaceAll("\\s*(hour|hr)s?\\s*", "H");
adjusted = adjusted.replaceAll("\\s*mins?\\s*", "M");
adjusted = adjusted.replaceAll("\\s*secs?\\s*", "S");
Duration d = Duration.parse("PT" + adjusted);
double hours = d.toMillis() / 3600000d;
System.out.println(hours);
}
//tests
getDuration("1 hour 30 mins 20 secs");
getDuration("2 hrs 10 mins");
getDuration("45 mins");
The conclusion is the same.
PS: if your Java version is <= 7 then you can use ThreeTen Backport . The class name and methods are the same, the only difference is the package name: org.threeten.bp
instead of java.time
.
I am currently doing this:
private double convertToHours(String inputTime) {
inputTime = " 1 hour 30 mins 20 secs";
double hours = 0;
List<String> timeList = Arrays.asList(inputTime.split(" "));
ListIterator<String> iterator = timeList.listIterator();
String time = null;
String previous = null;
while (iterator.hasNext()) {
int prevIndex = iterator.previousIndex();
time = (String) iterator.next();
if (!time.isEmpty() && time != null) {
if (time.contains("hours") || time.contains("hrs") || time.contains("hr") || time.contains("hour")) {
// time = time.substring(0, time.indexOf('h'));
previous = timeList.get(prevIndex);
hours = hours + Double.parseDouble(previous.trim());
}
if (time.contains("mins") || time.contains("min") || time.contains("mns")) {
//time = time.substring(0, time.indexOf('m'));
previous = timeList.get(prevIndex);
hours = hours + Double.parseDouble(previous) / 60;
}
if (time.contains("secs") || time.contains("sec") || time.contains("scs")) {
//time = time.substring(0, time.indexOf('s'));
previous = timeList.get(prevIndex);
hours = hours + Double.parseDouble(previous) / 3600;
}
}
}
return hours;
}
source to share