Как сравнить две даты в JavaScript: полное руководство
Почему простое сравнение операторами работает, но не всегда
JavaScript позволяет сравнивать объекты Date операторами >, <, >=, <=. Это работает, потому что при сравнении объекты неявно преобразуются в числа (миллисекунды с 1 января 1970 года). Однако операторы == и === так не работают — они сравнивают ссылки на объекты, а не их значения. Поэтому new Date('2023-10-15') == new Date('2023-10-15') вернёт false, хотя даты одинаковые.
Лучший способ: преобразование в число через getTime()
Самый надёжный метод — использовать getTime(), который возвращает количество миллисекунд с 1 января 1970 года UTC. Это число можно сравнивать любыми операторами, включая ===.
const date1 = new Date('2023-10-15T10:00:00');
const date2 = new Date('2023-10-15T10:00:00');
// Проверка на равенство
if (date1.getTime() === date2.getTime()) {
console.log('Даты равны');
}
// Проверка на "раньше"
if (date1.getTime() < date2.getTime()) {
console.log('date1 раньше date2');
}
// Проверка на "позже"
if (date1.getTime() > date2.getTime()) {
console.log('date1 позже date2');
}
Альтернативные методы: valueOf() и Number()
Метод valueOf() делает то же самое, что и getTime(). Вы также можете использовать унарный плюс:
const date1 = new Date('2023-10-15');
const date2 = new Date('2023-10-20');
// Через valueOf()
if (date1.valueOf() < date2.valueOf()) {
console.log('date1 раньше');
}
// Через унарный плюс (преобразование в число)
if (+date1 < +date2) {
console.log('date1 раньше');
}
Проблема с временными зонами
Когда вы создаёте дату из строки в формате '2023-10-15' (только дата), JavaScript интерпретирует её как полночь по UTC. Если вы создаёте дату через new Date(2023, 9, 15) (месяцы с 0), то она будет в локальном часовом поясе. Это может привести к путанице при сравнении. Рекомендуется всегда использовать UTC или явно указывать часовой пояс.
// Создание даты в UTC
const utcDate = new Date(Date.UTC(2023, 9, 15)); // 15 октября 2023, 00:00 UTC
// Лучше избегать строковых форматов, если важна точность
const dateFromParts = new Date(2023, 9, 15); // Локальное время
Сравнение только дат (без времени)
Если нужно сравнить только день, месяц и год, игнорируя время, обнулите часы, минуты, секунды и миллисекунды:
function compareDatesOnly(date1, date2) {
const d1 = new Date(date1.getFullYear(), date1.getMonth(), date1.getDate());
const d2 = new Date(date2.getFullYear(), date2.getMonth(), date2.getDate());
if (d1.getTime() === d2.getTime()) return 'равны';
if (d1.getTime() < d2.getTime()) return 'первая раньше';
return 'первая позже';
}
// Пример
const a = new Date('2023-10-15T23:59:59');
const b = new Date('2023-10-16T00:00:00');
console.log(compareDatesOnly(a, b)); // "первая раньше" — игнорируем время
Итог: универсальная функция сравнения
function compareDates(date1, date2, ignoreTime = false) {
const d1 = ignoreTime
? new Date(date1.getFullYear(), date1.getMonth(), date1.getDate())
: new Date(date1);
const d2 = ignoreTime
? new Date(date2.getFullYear(), date2.getMonth(), date2.getDate())
: new Date(date2);
const t1 = d1.getTime();
const t2 = d2.getTime();
if (t1 === t2) return 0;
return t1 < t2 ? -1 : 1;
}
// Использование:
const start = new Date('2023-10-15');
const end = new Date('2023-10-20');
console.log(compareDates(start, end)); // -1 (start раньше)
console.log(compareDates(end, start)); // 1 (end позже)
Избегайте библиотек, если вам нужно только сравнение — чистый JavaScript справляется отлично. Главное — всегда использовать getTime() или valueOf() для точного сравнения и помнить о временных зонах при создании дат.
Сравнение дат через операторы сравнения с явным приведением
Хотя метод getTime() — золотой стандарт, можно использовать и более короткий подход: просто вычесть даты друг из друга. Результат вычитания — разница в миллисекундах, которая может быть отрицательной, нулевой или положительной.
const date1 = new Date('2023-10-15');
const date2 = new Date('2023-10-20');
const diff = date2 - date1; // 432000000 (5 дней в миллисекундах)
if (diff > 0) {
console.log('date2 позже date1');
} else if (diff < 0) {
console.log('date2 раньше date1');
} else {
console.log('даты равны');
}
Этот метод работает, потому что оператор вычитания неявно вызывает valueOf() для обоих операндов. Однако он не подходит для проверки на строгое равенство (нужно дополнительно использовать getTime()).
Когда использовать библиотеки
Если в проекте уже есть moment.js или date-fns, можно воспользоваться их методами:
// date-fns
import { compareAsc, compareDesc, isEqual } from 'date-fns';
const a = new Date('2023-10-15');
const b = new Date('2023-10-20');
console.log(compareAsc(a, b)); // -1 (a раньше)
console.log(isEqual(a, b)); // false
Но для простого сравнения двух дат без дополнительных манипуляций (форматирование, манипуляции с временными зонами) библиотеки избыточны. Чистый JavaScript с getTime() — самый лёгкий и быстрый вариант.