Parsing time strings like “1h 30min”

前端 未结 6 693
遇见更好的自我
遇见更好的自我 2020-11-29 07:28

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-T

相关标签:
6条回答
  • 2020-11-29 07:40

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

    Duration d = Duration.parse("PT1H30M")
    

    You can convert this duration to the total length in milliseconds. Beware that Duration has a resolution of nanoseconds, so you may have data loss going from nanoseconds to milliseconds.

    long milliseconds = d.toMillis();
    

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

    0 讨论(0)
  • 2020-11-29 07:50

    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.

    Using 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);
    
    }
    
    0 讨论(0)
  • 2020-11-29 07:54

    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 appendSuffix that takes a variants parameter if you need to make it more flexible.

    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.

    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 DateTimeConstants class to avoid the need for magic numbers.)

    0 讨论(0)
  • 2020-11-29 07:55

    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.

    0 讨论(0)
  • 2020-11-29 07:56

    I realise this thread is a few years old but it keeps popping up at the top of a Google search so I thought we'd share this.

    We needed this capability as well on a couple of projects, so we created this small library for it: https://github.com/blueanvil/kotlin-duration-string

    It's written in/for Kotlin, but you can use it from Java code as well (see JavaTest.java):

    Duration duration = toDuration("24d 3h 45m");
    ...
    toHumanReadableString(duration);
    
    0 讨论(0)
  • 2020-11-29 07:58

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

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

    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();
    }
    
    
    0 讨论(0)
提交回复
热议问题