Есть ли библиотека Java, которая преобразует строки, описывающие меры времени (например, «1d 1m 1s») в миллисекунды? - PullRequest
8 голосов
/ 25 октября 2010

При настройке оценок проблем в JIRA вы можете ввести строку типа "1d 2h 30m", и JIRA преобразует это (я предполагаю) в соответствующее количество миллисекунд.

Существует ли доступная библиотека Java, котораяэто делает?

Я использую управляемый bean-компонент Spring, который принимает свойство, указывающее, как часто каталог должен очищаться, и я бы хотел, чтобы конфигурация принимала понятную человеку строку, а неявное количество миллисекунд.

В качестве альтернативы, если есть лучший подход, о котором я не думаю, я бы с удовольствием его услышал.

Ответы [ 6 ]

6 голосов
/ 25 октября 2010

Синтаксический анализатор не слишком сложен:

public static long parse(String input) {
   long result = 0;
   String number = "";
   for (int i = 0; i < input.length(); i++) {
     char c = input.charAt(i);
     if (Character.isDigit(c)) { 
       number += c; 
     } else if (Character.isLetter(c) && !number.isEmpty()) {
       result += convert(Integer.parseInt(number), c);
       number = "";
     }
   }
   return result;
}

private static long convert(int value, char unit) {
  switch(unit) {
    case 'd' : return value * 1000*60*60*24;
    case 'h' : return value * 1000*60*60;         
    case 'm' : return value * 1000*60;
    case 's' : return value * 1000;
  }
  return 0;
}

Код довольно устойчив к ошибкам, он просто игнорирует практически все, что не может декодировать (и игнорирует все пробелы, поэтому он принимает «1d 1s»)., "1s 1d", "1d20m300s" и т. Д.).

3 голосов
/ 25 октября 2010

Вот еще одно решение, которое можно настроить:

public class TimeReader{

    private final Map<String, Long> units = new HashMap<String, Long>();

    private static final String UNIT_PATTERN = "\\w+";
    private static final Pattern ITEM_PATTERN = Pattern.compile("(\\d+)\\s*("
        + UNIT_PATTERN + ")");

    /**
     * Add a new time unit.
     * 
     * @param unit
     *            the unit, e.g. "s"
     * @param value
     *            the unit's modifier value (multiplier from milliseconds, e.g.
     *            1000)
     * @return self reference for chaining
     */
    public TimeReader addUnit(final String unit, final long value){
        if(value < 0 || !unit.matches(UNIT_PATTERN)){
            throw new IllegalArgumentException();
        }
        units.put(unit, Long.valueOf(value));
        return this;
    }

    /**
     * Parse a string using the defined units.
     * 
     * @return the resulting number of milliseconds
     */
    public long parse(final String input){
        long value = 0l;
        final Matcher matcher = ITEM_PATTERN.matcher(input);
        while(matcher.find()){
            final long modifier = Long.parseLong(matcher.group(1));
            final String unit = matcher.group(2);
            if(!units.containsKey(unit)){
                throw new IllegalArgumentException("Unrecognized token: "
                    + unit);
            }
            value += units.get(unit).longValue() * modifier;
        }
        return value;
    }

}

Пример использования:

public static void main(final String[] args){
    final TimeReader timeReader =
        new TimeReader()
            .addUnit("h", 3600000l)
            .addUnit("m", 60000l)
            .addUnit("s", 1000l);

    System.out.println(timeReader.parse("3h, 2m   25  s"));
}

Вывод:

10945000

1 голос
/ 25 октября 2010

Взгляните на joda-time s PeriodConverter . Я никогда не использовал эту часть библиотеки joda-time самостоятельно, но, похоже, она делает то, что вам нужно.

В общем, что касается даты / времени, сначала посмотрите на joda-time:)

0 голосов
/ 25 октября 2010

Может быть cron выражений было бы более полезно для вашей текущей задачи: указать, как часто что-то должно происходить. Этот формат довольно гибкий, хорошо известный и понятный. Чтобы управлять вашим компонентом, который выполняет периодическую рутинную работу, вы можете использовать планировщик Quartz, аннотации таймера EJB3 или аннотации таймера Spring.

0 голосов
/ 25 октября 2010
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

public class DateTest {
    public static void main(String[] args) {
        DateFormat df = new SimpleDateFormat("dd'd' HH'h' mm'm'");
        try {
            Date d = df.parse("1d 2h 30m");
            System.out.println(d.getTime());
        } catch (ParseException e) {
            e.printStackTrace();
        }
    }
}
0 голосов
/ 25 октября 2010

Насколько я знаю, нет. Я полагаю, что вам придется преобразовать эти числа в Calendar (GregorianCalendar), а затем перейти к получению миллисекунд, которые вы, вероятно, уже знаете, поэтому вы опубликовали это в надежде на лучший ответ.

Мой голос: Если никто не может его найти, возможно, сейчас самое подходящее время, чтобы создать его самостоятельно и внести его в сообщество. :)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...