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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/6403851/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 15:46:37  来源:igfitidea点击:

Parsing time strings like "1h 30min"

javaparsingtimejodatime

提问by Jonik

Anyone know of a Java library that can parse time strings such as "30min" or "2h 15min" or "2d 15h 30min" as milliseconds (or some kind of Duration object). Can Joda-Time do something like this?

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

(I have an ugly long method to maintain that does such parsing and would like to get rid of it / replace it with something that does a better job.)

(我有一个丑陋的长方法来维护它进行这样的解析,并希望摆脱它/用更好的东西替换它。)

采纳答案by Brad Mace

You'll probably have to tweak this a bit for your own format, but try something along these lines:

您可能需要为自己的格式稍微调整一下,但请尝试以下方式:

PeriodFormatter formatter = new PeriodFormatterBuilder()
    .appendDays().appendSuffix("d ")
    .appendHours().appendSuffix("h ")
    .appendMinutes().appendSuffix("min")
    .toFormatter();

Period p = formatter.parsePeriod("2d 5h 30min");

note that there is a appendSuffixthat takes a variantsparameter if you need to make it more flexible.

请注意,如果您需要使其更灵活appendSuffix,则可以使用一个variants参数。

Update: Joda Time has since added Period.toStandardDuration(), and from there you can use getStandardSeconds()to get the elapsed time in seconds as a long.

更新:Joda Time 已添加Period.toStandardDuration(),从那里您可以使用getStandardSeconds()以秒为单位的已用时间作为long.

If you're using an older version without these methods you can still calculate a timestamp yourself by assuming the standard 24/hr in a day, 60min/hr, etc. (In this case, take advantage of the constants in the DateTimeConstantsclass to avoid the need for magic numbers.)

如果您使用的是没有这些方法的旧版本,您仍然可以通过假设标准的一天 24/小时、60 分钟/小时等来自己计算时间戳(在这种情况下,利用类中的常量DateTimeConstants来避免需要神奇的数字。)

回答by Andrejs

Duration parsing is now included in Java 8. Use standard ISO 8601format with Duration.parse.

持续时间解析现在包含在Java 8 中。使用标准ISO 8601格式和Duration.parse.

Duration d = Duration.parse("PT1H30M")

You can convert this durationto the total length in milliseconds. Beware that Durationhas a resolution of nanoseconds, so you may have data loss going from nanosecondsto milliseconds.

您可以将此持续时间转换为以毫秒为单位的总长度。请注意,Duration分辨率为纳秒,因此您可能会丢失从纳秒毫秒的数据

long milliseconds = d.toMillis();

The format is slightly different than what you describe but could be easily translated from one to another.

该格式与您所描述的略有不同,但可以轻松地从一种格式转换为另一种格式。

回答by Victor

I wanted to make the day, hour and minute optional and this seems to work to do that. Note that the appendSuffix() calls do not have a space after the character.

我想让日期、小时和分钟成为可选的,这似乎可以做到这一点。请注意, appendSuffix() 调用在字符后没有空格。

Using Joda 2.3.

使用 Joda 2.3。

PeriodParser parser = new PeriodFormatterBuilder()
        .appendDays().appendSuffix("d").appendSeparatorIfFieldsAfter(" ")
        .appendHours().appendSuffix("h").appendSeparatorIfFieldsAfter(" ")
        .appendMinutes().appendSuffix("min")
        .toParser();

The above code passes these tests.

上面的代码通过了这些测试。

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

}

回答by bekce

FYI, Just wrote this for hour+ periods, only uses java.time.*, pretty simple to understand and customize for any need;

仅供参考,只写了一个小时以上的时间,只使用java.time.*,非常容易理解和定制以满足任何需要;

This version works with strings like; 3d12h, 2y, 9m10d, etc.

这个版本适用于像这样的字符串;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();
}

回答by MJB

No, Joda defaults to taking only Durations, Instant intervals, and objects. For the latter it accepts things like Dates or SOAP ISO format. You can add you own converter here for the Duration class, and admittedly that would hide all your ugly code.

不,Joda 默认仅采用持续时间、即时间隔和对象。对于后者,它接受日期或 SOAP ISO 格式等内容。您可以在此处为 Duration 类添加您自己的转换器,无可否认,这会隐藏您所有丑陋的代码。