Библиотека js-joda предоставляет строгую модель работы с датой и
временем, основанную на API Java java.time. Одной из
ключевых возможностей библиотеки является корректное сравнение временных
объектов: дат, времени, дат со временем, периодов и длительностей.
В отличие от стандартного объекта Date, сравнение в
Js-joda построено на неизменяемых типах и предсказуемых правилах.
Практически все временные типы поддерживают методы:
equals()isBefore()isAfter()compareTo()Наиболее часто используются:
const { LocalDate } = require('@js-joda/core');
const first = LocalDate.parse('2025-03-10');
const second = LocalDate.parse('2025-03-15');
console.log(first.isBefore(second)); // true
console.log(first.isAfter(second)); // false
console.log(first.equals(second)); // false
Метод equals() проверяет полное равенство объектов.
const { LocalDate } = require('@js-joda/core');
const a = LocalDate.of(2025, 5, 1);
const b = LocalDate.of(2025, 5, 1);
console.log(a.equals(b)); // true
Важно понимать: сравнивается именно значение даты, а не ссылка на объект.
===console.log(a === b); // false
Оператор === сравнивает ссылки в памяти, а
equals() — содержимое объектов.
Метод isBefore() проверяет, находится ли текущий объект
раньше другого.
const start = LocalDate.parse('2025-01-01');
const end = LocalDate.parse('2025-12-31');
console.log(start.isBefore(end)); // true
const { LocalTime } = require('@js-joda/core');
const morning = LocalTime.parse('09:00');
const evening = LocalTime.parse('18:00');
console.log(morning.isBefore(evening)); // true
Метод работает противоположным образом.
const later = LocalDate.parse('2025-08-01');
const earlier = LocalDate.parse('2025-02-01');
console.log(later.isAfter(earlier)); // true
compareTo() возвращает числовой результат:
0 — объекты равныconst d1 = LocalDate.parse('2025-04-01');
const d2 = LocalDate.parse('2025-04-10');
console.log(d1.compareTo(d2)); // -9
console.log(d2.compareTo(d1)); // 9
Метод особенно полезен при сортировке.
const dates = [
LocalDate.parse('2025-06-10'),
LocalDate.parse('2025-01-01'),
LocalDate.parse('2025-03-15')
];
dates.sort((a, b) => a.compareTo(b));
console.log(dates);
Тип LocalDateTime сравнивает одновременно и дату, и
время.
const { LocalDateTime } = require('@js-joda/core');
const first = LocalDateTime.parse('2025-05-01T10:00');
const second = LocalDateTime.parse('2025-05-01T12:00');
console.log(first.isBefore(second)); // true
Сначала сравнивается:
Тип ZonedDateTime учитывает временную зону.
const { ZonedDateTime, ZoneId } = require('@js-joda/core');
const moscow = ZonedDateTime.now(ZoneId.of('Europe/Moscow'));
const tokyo = ZonedDateTime.now(ZoneId.of('Asia/Tokyo'));
console.log(moscow.isBefore(tokyo));
Сравнение происходит по глобальному времени UTC, а не по локальному отображению.
Например:
const a = ZonedDateTime.parse('2025-05-01T10:00+03:00[Europe/Moscow]');
const b = ZonedDateTime.parse('2025-05-01T09:00+02:00[Europe/Berlin]');
console.log(a.equals(b)); // true
Обе даты представляют один и тот же момент времени.
Тип Instant предназначен для абсолютного времени.
const { Instant } = require('@js-joda/core');
const i1 = Instant.parse('2025-05-01T10:00:00Z');
const i2 = Instant.parse('2025-05-01T11:00:00Z');
console.log(i1.isBefore(i2)); // true
Instant особенно удобен:
Тип Duration хранит длительность во времени.
const { Duration } = require('@js-joda/core');
const duration = Duration.ofHours(-5);
console.log(duration.toHours()); // -5
Для получения абсолютного значения используется
abs().
const positive = duration.abs();
console.log(positive.toHours()); // 5
Period работает с календарными единицами:
const { Period } = require('@js-joda/core');
const period = Period.of(0, -3, -10);
console.log(period.months()); // -3
console.log(period.days()); // -10
const absolute = period.abs();
console.log(absolute.months()); // 3
console.log(absolute.days()); // 10
Очень распространённая задача — определить, находится ли дата внутри диапазона.
const current = LocalDate.parse('2025-06-15');
const start = LocalDate.parse('2025-06-01');
const end = LocalDate.parse('2025-06-30');
const inside =
!current.isBefore(start) &&
!current.isAfter(end);
console.log(inside); // true
Иногда требуется строгая проверка без включения границ.
const inside =
current.isAfter(start) &&
current.isBefore(end);
const today = LocalDate.now();
const target = LocalDate.parse('2025-12-31');
if (target.isAfter(today)) {
console.log('Дата ещё не наступила');
}
const expiration = LocalDate.parse('2025-01-01');
if (LocalDate.now().isAfter(expiration)) {
console.log('Срок истёк');
}
const dates = [
LocalDate.parse('2025-07-01'),
LocalDate.parse('2025-01-15'),
LocalDate.parse('2025-11-20')
];
const min = dates.reduce((a, b) =>
a.isBefore(b) ? a : b
);
console.log(min.toString());
const max = dates.reduce((a, b) =>
a.isAfter(b) ? a : b
);
const events = [
{
title: 'Meeting',
date: LocalDate.parse('2025-06-10')
},
{
title: 'Conference',
date: LocalDate.parse('2025-01-20')
},
{
title: 'Release',
date: LocalDate.parse('2025-04-15')
}
];
events.sort((a, b) =>
a.date.compareTo(b.date)
);
console.log(events);
const d1 = Duration.ofMinutes(30);
const d2 = Duration.ofHours(1);
console.log(d1.compareTo(d2)); // отрицательное число
const a = Duration.ofSeconds(60);
const b = Duration.ofMinutes(1);
console.log(a.equals(b)); // true
Period сравнивать сложнее, поскольку месяцы имеют разную
длину.
const p1 = Period.ofMonths(1);
const p2 = Period.ofDays(30);
Такие значения нельзя считать эквивалентными автоматически.
Поэтому Period не предназначен для прямого сравнения
продолжительности времени.
Js-joda строго разделяет типы.
Например:
const date = LocalDate.now();
const time = LocalTime.now();
date.equals(time);
Такой код всегда вернёт false, поскольку объекты
относятся к разным типам.
LocalDate можно преобразовать в количество дней от эпохи
Unix.
const date = LocalDate.parse('2025-05-10');
console.log(date.toEpochDay());
Это полезно:
const a = LocalDate.parse('2025-01-01').toEpochDay();
const b = LocalDate.parse('2025-12-31').toEpochDay();
console.log(a < b); // true
Для Instant существует метод:
instant.epochSecond()
Пример:
const first = Instant.parse('2025-05-01T00:00:00Z');
const second = Instant.parse('2025-05-02T00:00:00Z');
console.log(
first.epochSecond() <
second.epochSecond()
);
const duration = Duration.between(
LocalTime.parse('18:00'),
LocalTime.parse('10:00')
);
console.log(duration.toHours()); // -8
console.log(duration.abs().toHours()); // 8
const moscow = ZonedDateTime.parse(
'2025-05-01T15:00+03:00[Europe/Moscow]'
);
const london = ZonedDateTime.parse(
'2025-05-01T13:00+01:00[Europe/London]'
);
console.log(moscow.equals(london)); // true
Иногда важно игнорировать время.
const first = LocalDateTime.parse(
'2025-05-01T10:00'
);
const second = LocalDateTime.parse(
'2025-05-01T22:00'
);
console.log(
first.toLocalDate()
.equals(second.toLocalDate())
);
console.log(
first.toLocalTime()
.equals(second.toLocalTime())
);
Все объекты Js-joda неизменяемы.
const date = LocalDate.now();
const updated = date.plusDays(5);
console.log(date);
console.log(updated);
Сравнения никогда не изменяют исходные значения.
compareTo() реализован максимально эффективно:
Поэтому сортировка больших массивов работает значительно стабильнее по сравнению со строковым сравнением дат.
function isActive(start, end) {
const now = LocalDate.now();
return !now.isBefore(start) &&
!now.isAfter(end);
}
const active = isActive(
LocalDate.parse('2025-01-01'),
LocalDate.parse('2025-12-31')
);
console.log(active);
const { ChronoUnit } = require('@js-joda/core');
const first = LocalDate.parse('2025-01-01');
const second = LocalDate.parse('2025-01-20');
const diff = Math.abs(
ChronoUnit.DAYS.between(first, second)
);
console.log(diff); // 19
if (date.isBefore(limit)) {
console.log('Меньше');
} else if (date.isAfter(limit)) {
console.log('Больше');
} else {
console.log('Равны');
}
const target = LocalDate.parse('2030-01-01');
const isFuture = target.isAfter(LocalDate.now());
const isPast = target.isBefore(LocalDate.now());
console.log(isFuture);
console.log(isPast);
Js-joda поддерживает точность до наносекунд.
const first = LocalTime.parse('10:00:00.000000001');
const second = LocalTime.parse('10:00:00.000000002');
console.log(first.isBefore(second)); // true
Это особенно важно: