【发布时间】:2014-11-25 00:31:16
【问题描述】:
我有一些意见:
1h50m22s
2h40m10s
33m03s
我必须在 java 中转换为秒。
已经使用正则表达式 '\d+|\D+' 提取数字。
【问题讨论】:
-
如果你已经用正则表达式提取了数字,有什么问题?秒 = 小时 * 60 * 60 + 分钟 * 60 + 秒
-
这里的问题在哪里?
我有一些意见:
1h50m22s
2h40m10s
33m03s
我必须在 java 中转换为秒。
已经使用正则表达式 '\d+|\D+' 提取数字。
【问题讨论】:
不要重新发明轮子。 Joda-Time 库可以为您解析这些值。不需要正则表达式。
这些值接近标准ISO 8601 格式。特别是Durations 格式,PnYnMnDTnHnMnS。 P 标志着开始,T 将日期部分与时间位置分开。如果您只有时间值,那么只需在 PT 前面加上 PT33m03s。最后转大写得到PT33M03S。
Joda-Time 默认解析和生成这样的字符串。一旦您的输入采用标准格式,您就可以将其直接传递给 Joda-Time。跳过正则表达式。
或者,您可以指定 PeriodFormatter 以适合您的确切输入字符串。然后您可以解析原始输入字符串而无需转换为标准格式。
如果您对输入字符串的来源有任何控制或影响,我强烈建议您更改该来源以使用 ISO 8601 格式。
Period类接下来,使用Period 类将该值自动解析为 Period 对象。 Period 表示一个时间跨度,如数月、数天、数小时等。 不与宇宙历史时间轴上的点相关联。 (如果您在时间线上有特定点,请使用 Interval 类。)
Duration类接下来,调用toStandardDuration 以获取Duration 对象。 Joda-Time 中的持续时间表示时间跨度,就像时间的流逝一样。只是几毫秒,而不是特定的月数或小时数或类似的块。
最后,在 Duration 对象上调用 getStandardSeconds 以获得您的答案。
比处理正则表达式容易得多。并且更加可靠,因为 Joda-Time 已经构建、调试、使用良好,并且能够处理可能的输入字符串的各种排列。
使用 Joda-Time 2.5。
简洁的版本(不推荐)。
String input = ( "PT" + "33m03s" ).toUpperCase();
long durationInSeconds = Period.parse( input ).toStandardDuration().getStandardSeconds();
详细版本。
// Convert input string to standard ISO 8601 format.
// Alternatively, you could use a formatter to parse your original string rather than convert.
String inputRaw = "33m03s";
String inputStandard = "PT" + inputRaw; // Assuming this is a time-only without date portion, prepend 'PT' to make standard ISO 8601 format.
inputStandard = inputStandard.toUpperCase();
// Parse string as Period object.
Period period = Period.parse( inputStandard );
// Convert from Period to Duration to extract total seconds.
Duration duration = period.toStandardDuration();
long durationInSeconds = duration.getStandardSeconds(); // Returns getMillis() / 1000. The result is an integer division, so 2999 millis returns 2 seconds.
转储到控制台。
System.out.println( "inputRaw : " + inputRaw );
System.out.println( "inputStandard : " + inputStandard );
System.out.println( "period : " + period ); // Notice how the leading zero on the 'seconds' number is gone. We have a Period *object*, not messing with strings.
System.out.println( "duration : " + duration );
System.out.println( "durationInSeconds : " + durationInSeconds );
运行时。
inputRaw : 33m03s
inputStandard : PT33M03S
period : PT33M3S
duration : PT1983S
durationInSeconds : 1983
【讨论】:
您可以使用Joda-Time 轻松做到这一点。
首先使用 Pattern 类来提取字段:
Pattern pattern = Pattern.compile("(?:(\\d+)h)?(?:(\\d+)m)?(?:(\\d+)s)?");
Matcher matcher = pattern.matcher("1h50m22s");
matcher.matches();
String hours = matcher.group(1);
String minutes = matcher.group(2);
String seconds = matcher.group(3);
Period period = new Period();
if(hours != null){
period = period.withHours(Integer.parseInt(hours));
}
if(minutes != null){
period = period.withMinutes(Integer.parseInt(minutes));
}
if(seconds != null){
period = period.withSeconds(Integer.parseInt(seconds));
}
int totalSeconds = period.toStandardSeconds().getSeconds();
使用 PeriodFormatterBuilder 类(解析模式不太灵活):
String dateText = "1h50m22s";
PeriodFormatterBuilder formatterBuilder = new PeriodFormatterBuilder();
if(dateText.contains("h")){
formatterBuilder.appendHours().appendLiteral("h");
}
if(dateText.contains("m")){
formatterBuilder.appendMinutes().appendLiteral("m");
}
if(dateText.contains("s")){
formatterBuilder.appendSeconds().appendLiteral("s");
}
Period period = formatterBuilder.toFormatter().parsePeriod(dateText);
int totalSeconds = period.toStandardSeconds().getSeconds();
【讨论】:
您可能想使用 String 的 substring 方法来提取您想要的数字并将其解析为整数。例如,为了获得秒数,您可以这样做:
String time = "32h45m93s";
String seconds = time.substring(time.indexOf('m') + 1, time.indexOf('s'));
int seconds = Integer.parseInt(seconds);
我没有运行它,但这是一般的想法。对小时和分钟做同样的事情,然后
int totalSeconds = hours * 3600 + minutes * 60 + seconds;
【讨论】: