Сортировка массивов дат

Moment.js предоставляет мощный инструментарий для работы с датами и временем, что делает сортировку массивов дат удобной и наглядной. Для эффективной сортировки необходимо понимать внутреннее представление объектов Moment и методы сравнения дат.

Создание массива дат

Массив дат может быть создан как из строк, так и из объектов Date или объектов Moment:

const dates = [
    moment("2026-05-22"),
    moment("2024-12-31"),
    moment("2025-01-15"),
    moment("2026-01-01")
];

Каждая дата здесь представлена объектом Moment, который содержит методы для сравнения, форматирования и манипуляций с датой.

Сортировка по возрастанию

Для сортировки массива дат по возрастанию используется метод sort с функцией сравнения:

dates.sort((a, b) => a - b); // НЕ работает корректно, так как a и b — объекты Moment

Важно учитывать, что объекты Moment нельзя вычитать напрямую как числа. Для правильной сортировки необходимо использовать метод .valueOf(), который возвращает количество миллисекунд с начала эпохи Unix:

dates.sort((a, b) => a.valueOf() - b.valueOf());

После выполнения этого кода массив будет отсортирован от самой ранней даты к самой поздней.

Сортировка по убыванию

Для сортировки по убыванию используется аналогичный подход с изменённым знаком вычитания:

dates.sort((a, b) => b.valueOf() - a.valueOf());

Этот приём особенно полезен при отображении событий в обратном хронологическом порядке, например, последних транзакций или новостей.

Сравнение дат с помощью методов Moment.js

Moment.js предоставляет удобные методы для сравнения дат:

  • isBefore() — проверяет, находится ли дата раньше другой
  • isAfter() — проверяет, находится ли дата позже другой
  • isSame() — проверяет на полное совпадение даты и времени

Эти методы могут использоваться внутри сортировки для более читаемого кода:

dates.sort((a, b) => {
    if (a.isBefore(b)) return -1;
    if (a.isAfter(b)) return 1;
    return 0;
});

Этот подход обеспечивает наглядность, особенно при работе с массивами, содержащими объекты Moment с разными временными зонами.

Сортировка по дате без учета времени

Иногда требуется сортировать только по дате, игнорируя часы, минуты и секунды. Для этого Moment.js предоставляет метод .startOf('day'):

dates.sort((a, b) => a.startOf('day') - b.startOf('day')); // Не работает напрямую
dates.sort((a, b) => a.startOf('day').valueOf() - b.startOf('day').valueOf());

Таким образом, сортировка будет учитывать только год, месяц и день, игнорируя время суток.

Сортировка массивов с разными форматами даты

Если массив содержит строки дат в разных форматах, их сначала необходимо конвертировать в объекты Moment:

const stringDates = ["22-05-2026", "31/12/2024", "15-01-2025"];
const formattedDates = stringDates.map(d => moment(d, ["DD-MM-YYYY", "DD/MM/YYYY"]));
formattedDates.sort((a, b) => a.valueOf() - b.valueOf());

Использование массива форматов позволяет Moment корректно распознать различные форматы без ошибок преобразования.

Производительность и большие массивы

При сортировке больших массивов дат важно учитывать производительность. Методы Moment создают объекты с дополнительными свойствами, что может увеличивать нагрузку. Для очень больших массивов можно конвертировать даты в миллисекунды, отсортировать их, а затем при необходимости преобразовать обратно в объекты Moment:

const timestamps = dates.map(d => d.valueOf());
timestamps.sort((a, b) => a - b);
const sortedDates = timestamps.map(t => moment(t));

Этот подход снижает накладные расходы на создание новых объектов Moment во время сортировки.

Смешанные массивы Moment и Date

В случае массива, содержащего одновременно объекты Date и Moment, сортировку можно унифицировать с помощью метода moment():

const mixedDates = [new Date(2026, 4, 22), moment("2024-12-31")];
mixedDates.sort((a, b) => moment(a).valueOf() - moment(b).valueOf());

Это гарантирует корректное сравнение всех элементов массива, независимо от их исходного типа.

Использование lodash для удобной сортировки

Библиотека lodash предоставляет метод _.sortBy, который упрощает сортировку массивов с преобразованием к числовому значению:

const sortedDates = _.sortBy(dates, d => d.valueOf());

Этот подход сокращает количество кода и повышает читаемость, особенно при работе с комплексными массивами дат.

Практические советы

  • Всегда конвертировать строки и объекты Date в Moment перед сортировкой для единообразного сравнения.
  • Для сортировки по дате без времени использовать .startOf('day').
  • Для больших массивов оптимизировать через массив числовых значений (valueOf()).
  • Методы .isBefore() и .isAfter() полезны для наглядного кода и сложных условий.

С помощью этих приёмов можно реализовать сортировку массивов дат любой сложности, учитывая разные форматы, временные зоны и требования к точности времени.