Диапазоны дат используются, когда требуется представить временной
интервал в человекочитаемом виде: период отпуска, рабочие смены,
события, дедлайны, расписания. В JavaScript для этого применяется
расширение Intl.DateTimeFormat, предоставляющее метод
formatRange, который позволяет корректно форматировать
начало и конец интервала с учётом локали и правил сокращения.
formatRangeМетод formatRange доступен у экземпляра
Intl.DateTimeFormat и принимает две даты:
const formatter = new Intl.DateTimeFormat('ru-RU');
const start = new Date(2026, 0, 1);
const end = new Date(2026, 0, 10);
console.log(formatter.formatRange(start, end));
Результат будет зависеть от локали, но смысл всегда один — отображение интервала в компактной форме.
Intl.DateTimeFormat автоматически:
Одно из главных преимуществ formatRange —
интеллектуальное сокращение повторяющихся элементов.
const formatter = new Intl.DateTimeFormat('ru-RU', {
year: 'numeric',
month: 'long',
day: 'numeric'
});
const start = new Date(2026, 0, 1);
const end = new Date(2026, 0, 10);
console.log(formatter.formatRange(start, end));
Результат будет наподобие:
1–10 января 2026 г.
Повторяющиеся элементы (января 2026 г.) выводятся один
раз.
Алгоритм форматирования зависит от того, какие части даты различаются.
const start = new Date(2026, 0, 1);
const end = new Date(2026, 0, 2);
Вывод сокращается до:
1–2 января 2026 г.
const start = new Date(2026, 0, 25);
const end = new Date(2026, 1, 5);
Результат:
25 января – 5 февраля 2026 г.
const start = new Date(2025, 11, 31);
const end = new Date(2026, 0, 1);
Результат:
31 декабря 2025 – 1 января 2026 г.
Intl.DateTimeFormat позволяет управлять уровнем
детализации через опции.
const formatter = new Intl.DateTimeFormat('ru-RU', {
year: 'numeric',
month: 'long',
day: 'numeric'
});
const formatter = new Intl.DateTimeFormat('ru-RU', {
year: '2-digit',
month: '2-digit',
day: '2-digit'
});
Пример результата:
01.01.26–10.01.26
format и formatRangeМетод format используется для одной даты:
formatter.format(new Date());
Метод formatRange предназначен для интервалов:
formatter.formatRange(startDate, endDate);
Использование format для диапазона требует ручной сборки
строки:
`${formatter.format(start)} – ${formatter.format(end)}`
Однако такой подход не учитывает локальные правила сокращения и часто приводит к избыточному повторению данных.
Если обе даты совпадают, formatRange возвращает
единичное значение:
const date = new Date(2026, 0, 1);
formatter.formatRange(date, date);
Результат:
1 января 2026 г.
Это важное отличие от ручной конкатенации, где дублирование неизбежно.
Диапазоны могут включать не только даты, но и время.
const formatter = new Intl.DateTimeFormat('ru-RU', {
year: 'numeric',
month: '2-digit',
day: '2-digit',
hour: '2-digit',
minute: '2-digit'
});
const start = new Date(2026, 0, 1, 10, 0);
const end = new Date(2026, 0, 1, 12, 30);
console.log(formatter.formatRange(start, end));
Возможный результат:
01.01.2026, 10:00–12:30
Система автоматически убирает повторяющуюся дату.
Локаль влияет не только на формат, но и на порядок элементов.
new Intl.DateTimeFormat('ru-RU').formatRange(start, end);
1–10 января 2026 г.
new Intl.DateTimeFormat('en-US').formatRange(start, end);
Jan 1 – Jan 10, 2026
formatRangeToPartsМетод formatRangeToParts возвращает структурированное
представление диапазона.
const formatter = new Intl.DateTimeFormat('ru-RU');
const parts = formatter.formatRangeToParts(
new Date(2026, 0, 1),
new Date(2026, 0, 10)
);
console.log(parts);
Результат представляет собой массив объектов:
[
{ type: 'day', value: '1', source: 'startRange' },
{ type: 'literal', value: '–', source: 'shared' },
{ type: 'day', value: '10', source: 'endRange' },
{ type: 'month', value: 'января', source: 'shared' },
{ type: 'year', value: '2026', source: 'shared' }
]
sourcestartRange — часть начала диапазонаendRange — часть конца диапазонаshared — общие элементыconst formatter = new Intl.DateTimeFormat('ru-RU', {
year: 'numeric'
});
formatter.formatRange(
new Date(2025, 0, 1),
new Date(2027, 0, 1)
);
Результат:
2025–2027
const formatter = new Intl.DateTimeFormat('ru-RU', {
year: 'numeric',
month: 'short'
});
formatter.formatRange(
new Date(2026, 0, 1),
new Date(2026, 5, 1)
);
янв. – июн. 2026 г.
Алгоритм форматирования диапазонов не всегда симметричен:
Например, при слишком низкой детализации (только год) месяцы и дни полностью исчезают из вывода.
При использовании timeZone форматирование становится
детерминированным относительно выбранной зоны.
const formatter = new Intl.DateTimeFormat('ru-RU', {
timeZone: 'Europe/Moscow',
year: 'numeric',
month: 'long',
day: 'numeric'
});
Диапазоны интерпретируются в контексте указанной зоны, что важно при работе с глобальными системами расписаний.
Форматирование диапазонов применяется в:
Единообразное отображение интервалов снижает когнитивную нагрузку и устраняет необходимость ручной нормализации строк.
Ручная сборка диапазона:
`${start.toLocaleDateString()} - ${end.toLocaleDateString()}`
Проблемы:
formatRange решает эти проблемы через единый механизм
интернационализации, встроенный в движок JavaScript.