我想将以下格式的时间转换为几小时。
我输入的时间格式可能类似于
1 hour 30 mins 20 secs
2 hrs 10 mins
45 mins
而我的输出将是:
1.505
2.167
0.75
这些是时间。
目前我通过解析输入字符串1 hour 30 mins 20 secs
手动完成,查找单词hour/hours/hrs/hr
是否存在,然后取出前面的数字 - mins和secs相同。我使用公式手动将分钟和秒转换为小时。
我可以在Java中使用任何内置规定吗?
答案 0 :(得分:3)
另一种方法是将其解析为a Duration
,但您需要先改变格式。类似的东西:
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;
答案 1 :(得分:2)
通常我不推荐使用Joda-Time(因为它被新的Java API取代),但它是我所知道的唯一具有良好格式化程序/解析器的API。
您可以使用PeriodFormatterBuilder
类并使用appendSuffix
方法为每个字段定义单数和复数值的后缀:
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");
输出:
1.5055555555555555
2.1666666666666665
0.75
创建PeriodFormatter
的另一种方法是使用带有正则表达式的appendSuffix
。当你有很多不同的后缀选项时(例如{小时字段的hour
和hr
),这很有用:
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();
请注意,我还添加了appendSeparatorIfFieldsBefore(" ")
以表明它在下一个字段之前有空格。
这个版本的好处是你不需要预处理输入:
// no need to call replaceAll (take input just as it is)
Period p = formatter.parsePeriod(input);
输出与上述相同。
如@assylian's answer中所述,您可以使用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");
输出相同。
PS:如果您的Java版本是< = 7,则可以使用ThreeTen Backport。类名和方法是相同的,唯一的区别是包名:org.threeten.bp
而不是java.time
。
答案 2 :(得分:0)
目前我这样做:
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;
}