isWithinInterval для проверки диапазонов

Функция isWithinInterval из библиотеки date-fns предназначена для определения, находится ли заданная дата внутри указанного временного интервала. Это одна из базовых операций при работе с календарями, расписаниями, фильтрацией событий и любыми задачами, где требуется работа с диапазонами времени.

Функция работает с объектной моделью интервала и обеспечивает предсказуемое поведение без необходимости вручную сравнивать даты через >= и <=.


Сигнатура и структура данных

Функция имеет следующий формат:

isWithinInterval(date, interval)

Параметры

date Дата, которую необходимо проверить. Может быть:

  • объект Date
  • timestamp (число)
  • строка, приводимая к дате через Date.parse

interval Объект интервала с обязательными полями:

{
  start: Date,
  end: Date
}

Ключевая особенность — интервал всегда задаётся через два явных края: начало и конец.


Базовый пример использования

import { isWithinInterval } from 'date-fns'

const date = new Date(2024, 5, 15)

const interval = {
  start: new Date(2024, 5, 1),
  end: new Date(2024, 5, 30)
}

const result = isWithinInterval(date, interval)
// true

Дата 15 июня 2024 года находится между 1 и 30 июня включительно, поэтому результат — true.


Логика включительности границ

isWithinInterval использует включительные границы:

  • дата равная start считается внутри интервала
  • дата равная end также считается внутри интервала
const date = new Date(2024, 0, 1)

const interval = {
  start: new Date(2024, 0, 1),
  end: new Date(2024, 0, 10)
}

isWithinInterval(date, interval)
// true

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


Поведение на границах интервала

Проверка крайних значений:

const start = new Date(2024, 0, 1)
const end = new Date(2024, 0, 10)

isWithinInterval(start, { start, end }) // true
isWithinInterval(end, { start, end })   // true

Если требуется исключить границы, необходимо использовать комбинацию isAfter и isBefore.


Типичные сценарии применения

Фильтрация событий по диапазону

const events = [
  { title: 'A', date: new Date(2024, 4, 1) },
  { title: 'B', date: new Date(2024, 4, 10) },
  { title: 'C', date: new Date(2024, 4, 20) }
]

const range = {
  start: new Date(2024, 4, 5),
  end: new Date(2024, 4, 15)
}

const filtered = events.filter(event =>
  isWithinInterval(event.date, range)
)

// [{ title: 'B', date: ... }]

Проверка доступности ресурса

В системах бронирования:

const bookingDate = new Date(2024, 6, 10)

const unavailable = {
  start: new Date(2024, 6, 1),
  end: new Date(2024, 6, 20)
}

const isAvailable = !isWithinInterval(bookingDate, unavailable)

Валидация диапазонов ввода

function validateRange(start, end, target) {
  return isWithinInterval(target, { start, end })
}

Важные особенности работы

1. Порядок дат в интервале

start должен быть меньше или равен end. При нарушении логики результат становится некорректным.

Некоторые версии date-fns могут не выбрасывать ошибку, но поведение становится неопределённым.


2. Работа с временем внутри суток

Дата включает время, поэтому:

const start = new Date(2024, 0, 1, 10, 0)
const end = new Date(2024, 0, 1, 18, 0)

Проверка учитывает не только день, но и точное время.


3. Таймзоны

isWithinInterval работает с объектами Date в локальном или UTC-представлении, но не выполняет автоматическую нормализацию таймзон.

При работе с серверными данными важно, чтобы:

  • обе границы интервала были в одной системе (UTC или локальное время)
  • сравниваемая дата была в той же системе координат

Частые ошибки при использовании

Перепутанные границы интервала

const interval = {
  start: new Date(2024, 5, 30),
  end: new Date(2024, 5, 1)
}

Такой интервал логически некорректен. Проверка может дать неожиданный результат.


Использование строк без явного преобразования

isWithinInterval('2024-06-15', {
  start: new Date(2024, 5, 1),
  end: new Date(2024, 5, 30)
})

Строка будет приведена к дате, но это создаёт риск неоднозначного парсинга.


Игнорирование времени

const date = new Date(2024, 0, 1, 23, 59)

Даже если день совпадает, время может вывести значение за пределы интервала.


Сравнение с ручной проверкой

Эквивалентная логика без date-fns:

const result =
  date >= interval.start &&
  date <= interval.end

Однако isWithinInterval:

  • делает код более декларативным
  • уменьшает вероятность ошибок при чтении
  • унифицирует поведение во всём проекте

Комбинирование с другими функциями date-fns

Проверка относительно текущей даты

import { isWithinInterval, startOfDay, endOfDay } from 'date-fns'

const today = new Date()

const interval = {
  start: startOfDay(new Date(2024, 0, 1)),
  end: endOfDay(new Date(2024, 0, 31))
}

isWithinInterval(today, interval)

Использование с диапазонами месяцев

import { startOfMonth, endOfMonth } from 'date-fns'

const interval = {
  start: startOfMonth(new Date(2024, 5, 1)),
  end: endOfMonth(new Date(2024, 5, 1))
}

Поведение при работе с миллисекундами

Все сравнения происходят на уровне timestamp (миллисекунды с 1970 года), что делает проверку:

  • детерминированной
  • независимой от локальных форматов отображения
  • устойчивой к форматированию даты

Использование в фильтрации больших массивов

При обработке больших наборов данных функция часто используется в сочетании с Array.prototype.filter:

const result = dataset.filter(item =>
  isWithinInterval(item.createdAt, interval)
)

При необходимости оптимизации вычислений имеет смысл:

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

Сценарии в реальных приложениях

Календарные системы

  • выделение активных дней
  • проверка занятости слотов
  • фильтрация событий по неделям и месяцам

Финансовые системы

  • анализ транзакций за период
  • отчёты по диапазону дат
  • расчёт начислений

Логирование

  • выборка логов по временным окнам
  • поиск ошибок в интервале

Поведение при некорректных данных

Если передать некорректные даты:

isWithinInterval(new Date('invalid'), {
  start: new Date(),
  end: new Date()
})

результат будет false, поскольку некорректная дата преобразуется в Invalid Date, а её timestamp — NaN.


Связь с другими функциями date-fns

  • isBefore — проверка, что дата раньше
  • isAfter — проверка, что дата позже
  • isEqual — равенство дат
  • areIntervalsOverlapping — пересечение интервалов

isWithinInterval фактически является композиционной операцией над базовыми сравнениями.


Оптимизационные аспекты

Функция выполняет минимальный набор операций:

  • два числовых сравнения timestamp
  • без создания лишних структур
  • без мутаций данных

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