任何人都知道Java库可以解析时间字符串,如“30min”或“2h 15min”或“2d 15h 30min”,以毫秒(或某种Duration对象)。 Joda-Time可以这样做吗?
(我有一个难看的长方法来维护这种解析,并希望摆脱它/用更好的工作替换它。)
答案 0 :(得分:32)
你可能不得不为自己的格式稍微调整一下,但是可以尝试以下几点:
PeriodFormatter formatter = new PeriodFormatterBuilder()
.appendDays().appendSuffix("d ")
.appendHours().appendSuffix("h ")
.appendMinutes().appendSuffix("min")
.toFormatter();
Period p = formatter.parsePeriod("2d 5h 30min");
请注意,如果您需要使appendSuffix
参数更加灵活,则会variants
采用long
参数。
更新:Joda时间已添加Period.toStandardDuration()
,您可以使用getStandardSeconds()
以DateTimeConstants
的形式获取经过的时间(以秒为单位)。< / p>
如果您使用的是没有这些方法的旧版本,您仍然可以通过假设一天中标准24小时,60分钟/小时等来自行计算时间戳。(在这种情况下,请利用中的常量) {{1}}课程,以避免需要魔术数字。)
答案 1 :(得分:25)
持续时间解析现已包含在Java 8中。将标准ISO 8601格式与Duration.parse
一起使用。
Duration d = Duration.parse("PT1H30M")
您可以convert this duration到总长度(以毫秒为单位)。请注意,Duration
的分辨率为纳秒,因此您可能会将数据丢失从nanoseconds升级到milliseconds。
long milliseconds = d.toMillis();
格式与您描述的格式略有不同,但可以轻松地从一个格式转换为另一个格式。
答案 2 :(得分:14)
我想让日,小时和分钟可选,这似乎可以做到这一点。请注意,appendSuffix()调用在字符后面没有空格。
使用Joda 2.3。
PeriodParser parser = new PeriodFormatterBuilder()
.appendDays().appendSuffix("d").appendSeparatorIfFieldsAfter(" ")
.appendHours().appendSuffix("h").appendSeparatorIfFieldsAfter(" ")
.appendMinutes().appendSuffix("min")
.toParser();
上面的代码通过了这些测试。
@Test
public void testConvert() {
DurationConverter c = new DurationConverter();
Duration d;
Duration expected;
d = c.convert("1d");
expected = Duration.ZERO
.withDurationAdded(Duration.standardDays(1),1);
assertEquals(d, expected);
d = c.convert("1d 1h 1min");
expected = Duration.ZERO
.withDurationAdded(Duration.standardDays(1),1)
.withDurationAdded(Duration.standardHours(1),1)
.withDurationAdded(Duration.standardMinutes(1),1);
assertEquals(d, expected);
d = c.convert("1h 1min");
expected = Duration.ZERO
.withDurationAdded(Duration.standardHours(1),1)
.withDurationAdded(Duration.standardMinutes(1),1);
assertEquals(d, expected);
d = c.convert("1h");
expected = Duration.ZERO
.withDurationAdded(Duration.standardHours(1),1);
assertEquals(d, expected);
d = c.convert("1min");
expected = Duration.ZERO
.withDurationAdded(Duration.standardMinutes(1),1);
assertEquals(d, expected);
}
答案 3 :(得分:0)
不,Joda默认只采用持续时间,即时间隔和对象。对于后者,它接受诸如Dates或SOAP ISO格式之类的东西。你可以在这里为Duration类添加你自己的转换器,不可否认,这会隐藏你所有丑陋的代码。
答案 4 :(得分:0)
仅供参考,仅用了一个小时以上的时间,仅使用java.time.*
,就很容易理解和自定义任何需求;
此版本适用于类似字符串; 3d12h
,2y
,9m10d
等
import java.time.Duration;
import java.time.Instant;
import java.time.Period;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.Locale;
private static final Pattern periodPattern = Pattern.compile("([0-9]+)([hdwmy])");
public static Long parsePeriod(String period){
if(period == null) return null;
period = period.toLowerCase(Locale.ENGLISH);
Matcher matcher = periodPattern.matcher(period);
Instant instant=Instant.EPOCH;
while(matcher.find()){
int num = Integer.parseInt(matcher.group(1));
String typ = matcher.group(2);
switch (typ) {
case "h":
instant=instant.plus(Duration.ofHours(num));
break;
case "d":
instant=instant.plus(Duration.ofDays(num));
break;
case "w":
instant=instant.plus(Period.ofWeeks(num));
break;
case "m":
instant=instant.plus(Period.ofMonths(num));
break;
case "y":
instant=instant.plus(Period.ofYears(num));
break;
}
}
return instant.toEpochMilli();
}
答案 5 :(得分:0)
我知道此线程已有几年历史,但是它一直在Google搜索的顶部弹出,因此我想我们应该分享一下。
我们在几个项目上也需要此功能,因此我们为此创建了一个小型库:https://github.com/blueanvil/kotlin-duration-string
它是用Kotlin编写的,但也可以通过Java代码使用它(请参见JavaTest.java):
Duration duration = toDuration("24d 3h 45m");
...
toHumanReadableString(duration);