Подтвердить что ты не робот

Строки времени анализа, такие как "1h 30min",

Кто-нибудь знает библиотеку Java, которая может анализировать временные строки, такие как "30min" или "2h 15min" или "2d 15h 30min" в миллисекундах (или какой-то объект Duration). Может ли Joda-Time сделать что-то вроде этого?

(У меня есть уродливый длинный метод поддержки, который выполняет такой синтаксический анализ и хотел бы избавиться от него/заменить его чем-то, что делает лучшую работу.)

4b9b3361

Ответ 1

Вам, вероятно, придется немного подкорректировать это для своего собственного формата, но попробуйте что-то в этом направлении:

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

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

обратите внимание, что существует appendSuffix, который принимает параметр variants, если вам нужно сделать его более гибким.

Обновление: Joda Time с тех пор добавила Period.toStandardDuration(), и оттуда вы можете использовать getStandardSeconds(), чтобы получить прошедшее время в секундах как long.

Если вы используете более старую версию без этих методов, вы все равно можете вычислить временную метку самостоятельно, приняв стандарт 24 часа в час, 60 минут/час и т.д. (В этом случае воспользуйтесь константами в DateTimeConstants, чтобы избежать необходимости в магических числах.)

Ответ 2

Разбор длительности теперь включен в Java 8. Используйте стандартный ISO 8601 формат с Duration.parse.

Duration d = Duration.parse("PT1H30M")

Вы можете преобразовать эту продолжительность в общую длину в миллисекундах. Помните, что Duration имеет разрешение наносекунд, поэтому вы можете потерять данные из nanoseconds в миллисекунды.

long milliseconds = d.toMillis();

Формат немного отличается от того, что вы описываете, но может быть легко переведен из одного в другой.

Ответ 3

Я хотел сделать день, час и минуту необязательными, и это, похоже, работает для этого. Обратите внимание, что вызовы 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);

}

Ответ 4

Нет, Joda по умолчанию использует только длительности, мгновенные интервалы и объекты. Для последнего он принимает такие вещи, как Даты или формат SOAP ISO. Вы можете добавить свой собственный конвертер здесь для класса Duration, и, по общему признанию, это скроет весь ваш уродливый код.

Ответ 5

К вашему сведению, только что написал это для периодов hour+, использует только java.time.*, Довольно простой для понимания и настройки для любых 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();
}