Фильтровать дату с помощью Java - PullRequest
0 голосов
/ 28 сентября 2018

Я пробую фильтры с помощью Java, я не могу использовать "Выбрать ..." для поиска результатов.

Проблема в том, что мой объект всегда включается в мой массив.

Мойданные ->

Registro 1-> Fecha Inicio "2018-09-01" , Fecha Fin -> "2018-09-30"
Registro 2-> Fecha inicio "2018-10-01" , Fecha Fin -> "2018-10-05"
Registro 3-> Fecha inicio "2017-12-31" , Fecha Fin -> "2018-11-30"
Registro 4-> Fecha inicio "2018-12-01" , Fecha Fin -> "2019-10-01"
Registro 5-> Fecha inicio "2018-12-30" , Fecha Fin -> "2018-12-31"
Registro 6-> Fecha inicio "2018-11-30" , Fecha Fin -> "2018-12-01"

Пользовательская вставка -> "2018-12-01" hasta el "9999-31-12" для фильтра.

Регистр 4 должен быть вставлен в массив, потому что мой пользователь вставил "2018-12-01" и мойрегистр имеет ту же дату начала.

Регистр 5º должен быть вставлен в массив, потому что мой пользователь вставил "2018-12-01" and finish year->9999 ТОГДА, как мой регистр между, Он должен вставить в массив.

Регистр 6º -> должно быть вставлено в массив, потому что дата окончания, потому что его дата окончания соответствует периоду времени между датой начала и датой окончания пользователя, то есть пользователь хочет от «2018-12-01» до «9999-31-12 "и дата Конец регистрации -" 2018-12-01 "

public List<Article> filterResult(String paramSelect, String dateStart, String dateEnd) {
    List<Article> list = Collections.emptyList();

    try {
        // Sino me ponen fecha de fin, la establezco al máximo.
        if(dateStart != null && dateEnd == null) {
            dateEnd ="9999-31-12";
            list = (List<Article>) this.pgRepository.findAll();
            list =  this.getStart(list, dateStart, dateEnd);
        }
     } catch (Exception e) {
         LOGGER.error(e.getMessage());
     }

     return list;
}

private List<Article> getStart(List<Article> list, String dateStart, String dateEnd) throws ParseException {
    DateFomrat df = new SimpleDateFormat("yyyy-MM-dd"); 
    Date userDate = df.parse(dateStart);
    Date userEnd = df.parse(dateEnd);

    List<Article> filter = new ArrayList<Article>();

    for(Article param : list) {
        Date paramStart = df.parse(param.getStartdatevalidity());
        Date paramEnd = df.parse(param.getEnddatevalidity());

        if(paramStart.after(userDate) || paramEnd.before(userDate) && paramStart.after(userEnd) ||  paramEnd.before(userEnd)) {
            filter.add(param);
        }
    }

    return filter;
}

У меня две проблемы -> 1º Мой объект всегда защищен в моем массиве. 2º Я не знаю,моя логика верна ...

Спасибо и извините за мой английский.

Ответы [ 3 ]

0 голосов
/ 30 сентября 2018

Я думаю, что вы хотите это:

    if (! (paramEnd.before(userDate) || paramStart.after(userEnd))) {
        filter.add(param);
    }

Да, это просто.Вы можете сказать, что я изменил условие.Вам не нужны статьи, срок действия которых заканчивается до userDate, а также не нужны статьи, срок действия которых начинается после userEnd.Все остальные статьи перекрываются с пользовательским интервалом, поэтому они включены.

Тем не менее используемый вами класс Date давно устарел и имеет ряд проблем с дизайном.И SimpleDateFormat славится проблемами.Кроме того, Date, несмотря на свое название, представляет собой не дату, а момент времени.Я рекомендую вам использовать LocalDate из java.time, современного Java-API даты и времени, для представления даты как внутри вашего Article класса, так и в коде поиска и фильтрации.В качестве дополнительного бонуса LocalDate анализирует ваш формат даты yyyy-MM-dd без какого-либо явного средства форматирования, поскольку этот формат является стандартным (он также известен как ISO 8601).Например:

public class Article {

    LocalDate startDateValidity;
    LocalDate endDateValidity;

    // Note that this constructor accepts string arguments for convenience
    public Article(String startValidity, String endValidity) {
        this.startDateValidity = LocalDate.parse(startValidity);
        this.endDateValidity = LocalDate.parse(endValidity);
    }

    // getters etc.

}

В filterResult парсинг dateStart и dateEnd в LocalDate в том же выражении, что и в конструкторе выше.Если dateEnd отсутствует, установите userEnd tp LocalDate.MAX.Ваше if условие не сильно меняется, когда все даты LocalDate;перед именами методов стоит is:

    if (! (paramEnd.isBefore(userDate) || paramStart.isAfter(userEnd))) {
        filter.add(param);
    }

РЕДАКТИРОВАТЬ: давайте проверим это.

Используя даты 6 регистраций из вашего вопроса:

    List<Article> list = Arrays.asList(
            new Article("2018-09-01", "2018-09-30"),
            new Article("2018-10-01", "2018-10-05"),
            new Article("2017-12-31", "2018-11-30"),
            new Article("2018-12-01", "2019-10-01"),
            new Article("2018-12-30", "2018-12-31"),
            new Article("2018-11-30", "2018-12-01"));

    LocalDate userDate = LocalDate.parse("2018-12-01");
    LocalDate userEnd = LocalDate.MAX;

    for(Article param : list) {
        LocalDate paramStart = param.getStartDateValidity();
        LocalDate paramEnd = param.getEndDateValidity();

        if (! (paramEnd.isBefore(userDate) || paramStart.isAfter(userEnd))) {
            System.out.println("Included " + param);
        }
    }

Этот фрагмент напечатал следующий вывод:

Included Article [startDateValidity=2018-12-01, endDateValidity=2019-10-01]
Included Article [startDateValidity=2018-12-30, endDateValidity=2018-12-31]
Included Article [startDateValidity=2018-11-30, endDateValidity=2018-12-01]

Вы узнаете даты регистраций № 4, 5 и 6, которые, как вы сказали, вы хотели бытьвставлен в массив фильтров.

Что пошло не так в вашем коде?

У меня две проблемы -> 1º Мой объект всегда защищен в моем массиве.2º Я не знаю, правильна ли моя логика ...

Вы правы, что ваша логика неверна.Давайте посмотрим на ваше if условие:

if(paramStart.after(userDate)
        || paramEnd.before(userDate) && paramStart.after(userEnd)
        || paramEnd.before(userEnd)) …

&& имеет более высокий приоритет, чем ||, поэтому оно интерпретируется так, как будто в скобках paramEnd.before(userDate) && paramStart.after(userEnd).Однако эта средняя часть условия реально никогда не будет истинной, но статья будет включена, если первая или последняя часть соответствуют действительности.Только регистрация номер 5 выполняет первую часть условия, потому что after означает «строго после».Однако все 6 регистраций выполняют последнюю часть, paramEnd.before(userDate) && paramStart.after(userEnd)|| между частями этого достаточно, чтобы все 6 статей были включены в результат фильтрации.

Ссылки

0 голосов
/ 30 сентября 2018

Я предлагаю вообще не использовать разбор дат от String до Date.Если данные хранятся и вводятся пользователем в одном и том же формате yyyy-mm-dd, то для сравнения двух дат достаточно просто сравнить две строки.

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

В этом случае ваш getStart() метод становится очень простым:

public static List<Article> getStart(List<Article> list, String dateStart, String dateEnd) {
    final Predicate<String> isInRange = date -> date.compareTo(dateStart) >= 0 && date.compareTo(dateEnd) <= 0;
    final Predicate<Article> isIntersect = article -> isInRange.test(article.getStartdatevalidity()) || isInRange.test(article.getEnddatevalidity());
    return list.stream().filter(isIntersect).collect(Collectors.toList());
}
0 голосов
/ 29 сентября 2018

Редактировать 2 - убраны вопросы, заданные здесь для более ясного объяснения, так как концепция была получена благодаря ответу Оле В.В.

Мое предложение на основе предоставленных данных -

  1. Использование boolean java.util.Date.after(Date when)

    //Change suggestion in original code if(paramStart.after(userDate) || paramEnd.before(userDate) paramEnd.before(userEnd)) { filter.add(param); }

  2. Использование int java.util.Date.compareTo(java.util.Date anotherDate)

...