Как сортировать дату, которая находится в формате строки в java?

У меня есть arraylist со строковыми значениями, например

ArrayList<String> datestring=new ArrayList<String>();
datestring.add("01/21/2013 @03:13 PM");
datestring.add("01/21/2013 @04:37 PM");
datestring.add("01/21/2013 @10:41 AM");
datestring.add("01/21/2013 @10:48 AM");
datestring.add("01/22/2013 @06:16 AM");
datestring.add("01/22/2013 @06:19 AM");
datestring.add("01/21/2013 @05:19 PM");
datestring.add("01/21/2013 @05:19 PM");

Может ли кто-нибудь помочь мне в сортировке вышеуказанного списка? Таким образом, значения сортируются в соответствии с форматом AM и PM.
Ожидаемый результат после сортировки должен быть

for (String s : datestring)
{
    System.out.println(s);
}

.

01/21/2013 @10:41 AM;
01/21/2013 @10:48 AM;
01/21/2013 @03:13 PM;
01/21/2013 @04:37 PM;
01/21/2013 @05:16 PM;
01/21/2013 @05:19 PM;
01/22/2013 @06:16 AM;
01/22/2013 @06:19 AM;

Ответы

Ответ 1

попробуйте это

    Collections.sort(datestring, new Comparator<String>() {
        DateFormat f = new SimpleDateFormat("MM/dd/yyyy '@'hh:mm a");
        @Override
        public int compare(String o1, String o2) {
            try {
                return f.parse(o1).compareTo(f.parse(o2));
            } catch (ParseException e) {
                throw new IllegalArgumentException(e);
            }
        }
    });

или с Java 8

    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MM/dd/yyyy '@'hh:mm a");
    Collections.sort(datestring, (s1, s2) -> LocalDateTime.parse(s1, formatter).
            compareTo(LocalDateTime.parse(s2, formatter)));

Ответ 2

Хотя существует технический способ обойти вашу проблему, основной ошибкой является представление Date as String s, формы "примитивной одержимости". Если у вас есть текстовый ввод, преобразуйте его в java.util.Date или подходящий класс LocalDateTime (похоже, здесь подходит LocalDateTime). Эти классы реализуют Comparable из коробки, и сортировка их проста. Но у них также есть вся другая логика на борту, которую вам, вероятно, понадобятся при манипулировании экземплярами даты/времени, Strings этого не делают.

Обновить

Начиная с java 8, я бы рекомендовал вместо этого использовать свой класс LocalDateTime.

Ответ 3

java.time

Во-первых, поскольку Bowmore уже сказал, вы не должны держать строки в своем списке. Вместо этого используйте экземпляры классов java.time.

Храните объекты LocalDateTime. Или ZonedDateTime если вы знаете, в какой временной зоне это время. Строки хороши для представления пользователю, а не для манипуляций в вашей программе, таких как сортировка.

Следующий код преобразует ваш список в List<LocalDateTime>:

    DateTimeFormatter formatter 
            = DateTimeFormatter.ofPattern("MM/dd/uuuu '@'hh:mm a", Locale.ENGLISH);

    List<LocalDateTime> dateTimeList = datestring.stream()
            .map(ds -> LocalDateTime.parse(ds, formatter))
            .collect(Collectors.toCollection(ArrayList::new));

Теперь сортировка проста:

dateTimeList.sort(Comparator.naturalOrder());

LocalDateTime имеет естественный порядок, так как они реализуют Comparable, поэтому Comparator.naturalOrder() отлично подходит для сортировки. Другой способ получения такой же сортировки:

dateTimeList.sort(LocalDateTime::compareTo);

Чтобы представить отсортированные данные пользователю, мы хотим, конечно, форматировать даты-строки в строки:

dateTimeList.forEach(ldt -> System.out.println(ldt.format(formatter)));

Выход:

01/21/2013 @10:41 AM
01/21/2013 @10:48 AM
01/21/2013 @03:13 PM
01/21/2013 @04:37 PM
01/21/2013 @05:19 PM
01/21/2013 @05:19 PM
01/22/2013 @06:16 AM
01/22/2013 @06:19 AM

За исключением точек с запятой и одной простой опечатки, я считаю, что это именно то, о чем вы просили.

Ссылка: учебник Oracle: дата Время, объясняющее, как использовать java.time, современный Java-интерфейс даты и времени, который включает LocalDateTime и DateTimeFormatter.

Ответ 4

Можно сравнить List of date в строковом формате с помощью compareTo, как указано ниже.

ArrayList<String> datestring=new ArrayList<String>();
datestring.add("01/21/2013 @03:13 PM");
datestring.add("01/21/2013 @04:37 PM");
datestring.add("01/21/2013 @10:41 AM");
datestring.add("01/21/2013 @10:48 AM");
datestring.add("01/22/2013 @06:16 AM");
datestring.add("01/22/2013 @06:19 AM");
datestring.add("01/21/2013 @05:19 PM");
datestring.add("01/21/2013 @05:19 PM");

Collections.sort(datestring, new Comparator<String>() {
                @Override
                public int compare(String object1, String object2) {
                    return object1.compareTo(object2);
                }
            });

Используя это, вам даже не нужно разбирать строку в дату

Ответ 5

ArrayList не поддерживает сортировку по умолчанию. Вы можете использовать

public static <T> void sort(List<T> list, Comparator<? super T> c) из класса java.util.Collections. передайте свою реализацию компаратора для сортировки дат, что-то вроде

http://www.coderanch.com/t/392338/java/java/compare-Dates-String-Format

Ответ 6

Один из вариантов заключается в добавлении дат в TreeMap с неформатированной датой в качестве ключа и форматированной датой в качестве значения. Использование TreeMap автоматически сортирует значения.

private ArrayList<String> sortDates(ArrayList<String> dates) throws ParseException {
    SimpleDateFormat f = new SimpleDateFormat("dd MMM yyyy");
    Map <Date, String> dateFormatMap = new TreeMap<>();
    for (String date: dates)
        dateFormatMap.put(f.parse(date), date);
    return new ArrayList<>(dateFormatMap.values());
}

Ответ 7

Возможно, вы можете написать произвольный компаратор для сравнения строк и порядка даты на основе этого требования. Затем вы сможете отсортировать коллекцию с помощью реализованного компаратора.