Есть массив в котором лежат объекты с датами, необходимо отсортировать даты по убыванию
Дан массив:
const dates = [
{ date: "10.01.2017" },
{ date: "05.11.2016" },
{ date: "21.13.2002" },
]
Необходимо отсортировать массив по убыванию дат.
Примеры:
sortDates([
{"date": "05.11.2016"},
{"date": "21.13.2002"},
{"date": "10.01.2017"},
]) --> [
{"date": "10.01.2017"},
{"date": "05.11.2016"},
{"date": "21.01.2003"}
]
sortDates([
{"date": "10.01.1997"},
{"date": "05.11.1981"},
{"date": "21.13.2004"}
]) --> [
{"date": "21.01.2005"},
{"date": "10.01.1997"},
{"date": "05.11.1981"}
]
Теория: как решается задача по шагам
Почему нельзя сортировать строки напрямую
Строка "dd.mm.yyyy" при обычной сортировке строк сравнивает символы слева направо, поэтому лексикографический порядок не совпадает с хронологическим порядком дат.
Корректная сортировка требует привести дату либо к числу (timestamp), либо к строке формата, где порядок символов соответствует времени (например, "yyyy-mm-dd").
Почему нужен ручной разбор "dd.mm.yyyy"
Парсинг не-ISO форматов строк не гарантирован одинаково во всех реализациях, поэтому надежнее выделить dd, mm, yyyy регулярным выражением и преобразовать в числа.
Регулярное выражение ^(\d{2})\.(\d{2})\.(\d{4})$ гарантирует строго нужный формат, что упрощает обработку ошибок.
Нормализация переполнений в Date
При создании даты из числовых компонентов переполненные значения обычно “переносятся” (carry/borrow): лишние месяцы увеличивают год, значение дня 0 дает последний день предыдущего месяца, отрицательные значения уменьшают старшие компоненты.
Это позволяет преобразовать "21.13.2002" в "21.01.2003" без ручных вычислений: 13-й месяц становится январем следующего года при переносе.
Почему выбран UTC (а не local time)
Если создать дату как local time и затем форматировать ее, результат может зависеть от часового пояса и переходов на летнее/зимнее время, что иногда приводит к “сдвигам” при преобразованиях.
Для “чистых календарных дат” (без времени) стабильнее придерживаться UTC: создание через Date.UTC и форматирование через getUTC*.
Схема преобразования
- Вход: "dd.mm.yyyy".
- Шаг 1: выделение dd, mm, yyyy (regex).
- Шаг 2: построение UTC-даты
new Date(Date.UTC(yyyy, mm - 1, dd))(автонормализация). - Шаг 3: число для сортировки:
time = date.getTime(). - Шаг 4: сортировка по убыванию time.
- Шаг 5: форматирование результата в "dd.mm.yyyy" через
getUTC*иpadStart(2, "0").
Таблица: частые ошибки и решения
| Ошибка | Почему плохо | Как правильно |
|---|---|---|
new Date("10.01.2017") | Нестандартный формат, возможны различия интерпретации | Разбирать dd/mm/yyyy вручную и создавать дату из чисел |
| Месяц передается как 1..12 в конструктор из компонентов | В Date месяц обычно 0..11 | Использовать month - 1 |
| Форматирование через local getters | Возможна зависимость от часового пояса | Для “календарных дат” использовать getUTC* |
| Потеря ведущих нулей | "5.1.2017" не соответствует требуемому виду | Использовать padStart(2, "0") |
Кратко: необходимо разобрать "dd.mm.yyyy" на числа, создать дату через Date.UTC (что автоматически нормализует 13-й месяц), отсортировать по getTime() по убыванию и отформатировать обратно через UTC-геттеры с ведущими нулями.