Parsing duration string into milliseconds

2019-02-09 23:28发布

I need to parse a duration string, of the form 98d 01h 23m 45s into milliseconds.

I was hoping there was an equivalent of SimpleDateFormat for durations like this, but I couldn't find anything. Would anyone recommend for or against trying to use SDF for this purpose?

My current plan is to use regex to match against numbers and do something like

Pattern p = Pattern.compile("(\\d+)");
Matcher m = p.matcher("98d 01h 23m 45s");

if (m.find()) {
    int days = Integer.parseInt(m.group());
}
// etc. for hours, minutes, seconds

and then use TimeUnit to put it all together and convert to milliseconds.

I guess my question is, this seems like overkill, can it be done easier? Lots of questions about dates and timestamps turned up but this is a little different, maybe.

3条回答
太酷不给撩
2楼-- · 2019-02-10 00:05

Using a Pattern is a reasonable way to go. But why not use a single one to get all four fields?

Pattern p = Pattern.compile("(\\d+)d\\s+(\\d+)h\\s+(\\d+)m\\s+(\\d+)s");

Then use the indexed group fetch.

EDIT:

Building off of your idea, I ultimately wrote the following method

private static Pattern p = Pattern
        .compile("(\\d+)d\\s+(\\d+)h\\s+(\\d+)m\\s+(\\d+)s");

/**
 * Parses a duration string of the form "98d 01h 23m 45s" into milliseconds.
 * 
 * @throws ParseException
 */
public static long parseDuration(String duration) throws ParseException {
    Matcher m = p.matcher(duration);

    long milliseconds = 0;

    if (m.find() && m.groupCount() == 4) {
        int days = Integer.parseInt(m.group(1));
        milliseconds += TimeUnit.MILLISECONDS.convert(days, TimeUnit.DAYS);
        int hours = Integer.parseInt(m.group(2));
        milliseconds += TimeUnit.MILLISECONDS
                .convert(hours, TimeUnit.HOURS);
        int minutes = Integer.parseInt(m.group(3));
        milliseconds += TimeUnit.MILLISECONDS.convert(minutes,
                TimeUnit.MINUTES);
        int seconds = Integer.parseInt(m.group(4));
        milliseconds += TimeUnit.MILLISECONDS.convert(seconds,
                TimeUnit.SECONDS);
    } else {
        throw new ParseException("Cannot parse duration " + duration, 0);
    }

    return milliseconds;
}
查看更多
可以哭但决不认输i
3楼-- · 2019-02-10 00:07

Check out PeriodFormatter and PeriodParser from JodaTime library.

You can also use PeriodFormatterBuilder to build a parser for your strings like this

String periodString = "98d 01h 23m 45s";

PeriodParser parser = new PeriodFormatterBuilder()
   .appendDays().appendSuffix("d ")
   .appendHours().appendSuffix("h ")
   .appendMinutes().appendSuffix("m ")
   .appendSeconds().appendSuffix("s ")
   .toParser();

MutablePeriod period = new MutablePeriod();
parser.parseInto(period, periodString, 0, Locale.getDefault());

long millis = period.toDurationFrom(new DateTime(0)).getMillis();

Now, all this (especially the toDurationFrom(...) part) may look tricky, but I really advice you to look into JodaTime if you're dealing with periods and durations in Java.

Also look at this answer about obtaining milliseconds from JodaTime period for additional clarification.

查看更多
贼婆χ
4楼-- · 2019-02-10 00:25

The new java.time.Duration class in Java 8 let's you parse durations out of the box:

Duration.parse("P98DT01H23M45S").toMillis();

the format is slightly different so would need adjusting prior to parsing.

查看更多
登录 后发表回答