Как разобрать входной диапазон времени? - PullRequest
1 голос
/ 26 октября 2010

В программе, над которой я работаю, мне нужно, чтобы пользователь вводил временные диапазоны, такие как 2002-2003, или 1999- (подразумевается, присутствует), или -2000 (до 2000).

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

Итак, я взял диапазон дат, который они хотят, в виде строки, и у меня дата хранится в моем объекте как целое число.Я знаю случаи, и я пытался охватить все случаи, но у меня проблемы с «-2010» и «2010-», а также с «2010».

Случаи, насколькоЯ могу сказать следующее: -2010 2010 2010-2011 2011-

Может кто-нибудь предложить базовый алгоритм или, возможно, наметить некоторые полезные функции?

Моя идея заключалась в том, что к концу синтаксического анализа у меня должна быть минимальная и максимальная дата, чтобы я мог посмотреть на конкретную книгу и спросить, является ли предоставленная ею дата больше минимальной, именьше максимума?Но мне все еще нужно разобрать диапазоны.

Спасибо за помощь всем.

Ответы [ 4 ]

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

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

^ (\ d {4})? (-)? (\ D {4})? $ даст вам 3 группы вывода, вы проверяете каждую из них, чтобы увидеть, получили ли вы значение, и принимать решения на основе этого, и в качестве бонуса вам гарантировано, что они являются 4-значными числами. Посмотрите на группы на странице Rubular, на которую я ссылаюсь. Если у вас есть значение в группе 1, то это начальный год, «-» во второй группе, тогда это диапазон, значение в группе 3 - конечный диапазон. Делает логику действительно простой, и вам не нужно делать все эти глупые манипуляции со строками и целочисленные тесты, которые предлагают другие решения.

Так как это домашнее задание, вот что заставляет задуматься, как использовать Pattern и Matcher, я не собираюсь делать все это за вас.

import java.util.Arrays;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Main
{
    public static void main(String[] args)
    {
        final List<String> inputs = Arrays.asList("1999-", "-2010", "1990-2000", "1967");

        final Pattern p = Pattern.compile("^(\\d{4})?(-?)(\\d{4})?$");
        int count = 0;
        for (final String input : inputs)
        {
            final Matcher m1 = p.matcher(input);
            m1.find();
            System.out.format("Input: %d\n", count++);
            for (int i=1; i <= m1.groupCount(); i++)
            {
                System.out.format("\tGroup %d = %s\n", i, m1.group(i));
            }
        }
    }
}

Вот ожидаемый результат:

Input: 0
 Group 1 = 1999
 Group 2 = -
 Group 3 = null
Input: 1
 Group 1 = null
 Group 2 = -
 Group 3 = 2010
Input: 2
 Group 1 = 1990
 Group 2 = -
 Group 3 = 2000
Input: 3
 Group 1 = 1967
 Group 2 = 
 Group 3 = null

Как это работает:

^ - начало в начале строки
(\d{4})? - это ищет ровно 4 цифры \d, а () говорит, что группа находит то, что вы найдете, ? означает, что эта группа необязательна для совпадения, группа будет == null
(-)? - это выглядит для тире, ? делает его необязательным, () группирует результаты по выше
(\d{4})? - это ищет ровно 4 цифры \d, а () говорит, что группа находит то, что вы найдете, ? означает, что эта группа необязательна для совпадения, группа будет == null
$ - соответствует концу строки

Упражнение, оставленное читателю: Два случая, для которых он не «проверяет», - это пустая строка и «-», оба из которых следует рассматривать как «особые» случаи в зависимости от какой должна быть ваша бизнес-логика.

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

Проверьте, является ли первый символ -. Затем проверьте, является ли последний символ -. Если это не один из этих случаев, разделите на - (используйте метод split класса String).

0 голосов
/ 26 октября 2010
  1. Используйте StringTokenizer для разбора даты (или просто используйте метод String # indexOf)
  2. Используйте DateFormat для построения соответствующих дат
  3. Используйте методы объекта Date до / после для соответствующих сравнений, чтобы определить диапазон дат. http://download.oracle.com/javase/6/docs/api/
0 голосов
/ 26 октября 2010

Вы можете проанализировать с помощью функции String.indexOf ()

int startDate, endDate, middleIndex;
middleIndex = inputString.indexOf("-");
if (middleIndex == -1)       //If there's no hyphen
  startDate = endDate = Integer.parseInt(inputString);
else if (middleIndex == 0) {  //if the hyphen is at the start of the string
  startDate = null;
  endDate = Integer.parseInt(inputString.substring(1, inputString.length));
}
else if (middleIndex == inputString.length - 1) {  //if the hyphen is at the end of the string
  startDate = Integer.parseInt(inputString.substring(0, inputString.length - 1));
  endDate = null;
}
else {  //if the hyphen separates 2 years
  startDate = Integer.parseInt(inputString.substring(0, middleIndex));
  endDate = Integer.parseInt(inputString.substring(middleIndex + 1, inputString.length));
}
...