解析时间字符串,如“1h 30min”

时间:2011-06-19 17:09:55

标签: java parsing time jodatime

任何人都知道Java库可以解析时间字符串,如“30min”或“2h 15min”或“2d 15h 30min”,以毫秒(或某种Duration对象)。 Joda-Time可以这样做吗?

(我有一个难看的长方法来维护这种解析,并希望摆脱它/用更好的工作替换它。)

6 个答案:

答案 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.*,就很容易理解和自定义任何需求;

此版本适用于类似字符串; 3d12h2y9m10d

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);