Методы startOf и endOf в Day.js
используются для приведения даты к началу или концу выбранного
временного интервала. Они решают задачу нормализации времени при работе
с календарными операциями, фильтрацией диапазонов, построением отчётов и
сравнением дат на уровне дней, недель, месяцев и более крупных
единиц.
Любая дата в JavaScript содержит не только календарный день, но и точное время вплоть до миллисекунд. При аналитических или прикладных вычислениях часто требуется игнорировать «лишнюю точность» и работать с границами интервалов:
00:00:00.00023:59:59.99900:00:00.00023:59:59.999Методы startOf и endOf обеспечивают
стандартизированное приведение даты к таким границам.
Метод startOf(unit) возвращает новый объект даты,
округлённый вниз до начала указанной единицы времени.
Сигнатура:
dayjs().startOf(unit)
Где unit может принимать значения:
yearmonthweekdayhourminutesecondmillisecondstartOf обнуляет все младшие компоненты времени
относительно выбранной единицы:
month сбрасываются день, час, минута, секунда и
миллисекундыday сбрасывается только время сутокhour сбрасываются минуты, секунды и
миллисекундыПример:
const d = dayjs('2026-05-22T15:34:48.123');
d.startOf('day');
// 2026-05-22 00:00:00.000
d.startOf('month');
// 2026-05-01 00:00:00.000
d.startOf('year');
// 2026-01-01 00:00:00.000
Метод endOf(unit) возвращает дату, установленную на
последний момент указанной единицы времени.
Сигнатура:
dayjs().endOf(unit)
endOf выполняет противоположную операцию по отношению к
startOf, устанавливая максимальные значения для выбранного
уровня:
day — 23:59:59.999month — последний день месяца в
23:59:59.999year — 31 декабря в 23:59:59.999Пример:
const d = dayjs('2026-05-22T15:34:48.123');
d.endOf('day');
// 2026-05-22 23:59:59.999
d.endOf('month');
// 2026-05-31 23:59:59.999
d.endOf('year');
// 2026-12-31 23:59:59.999
Оба метода работают в рамках иерархии временных единиц. Каждая более крупная единица включает в себя более мелкие:
При вызове:
startOf('hour') обнуляются минуты, секунды и
миллисекундыstartOf('month') обнуляется всё ниже уровня дняДля week поведение зависит от локали и настройки начала
недели (понедельник или воскресенье), что может влиять на результат:
dayjs('2026-05-22').startOf('week');
Результат зависит от конфигурации локализации.
Обе функции не изменяют исходный объект, а возвращают новый экземпляр даты. Day.js придерживается неизменяемого подхода:
const a = dayjs('2026-05-22T10:00:00');
const b = a.startOf('day');
a.isSame(b); // false
Это важно при построении цепочек вычислений, где каждая операция должна сохранять промежуточные значения.
Ключевое различие заключается в направлении округления:
startOf — всегда в меньшую сторону (минимальное
значение интервала)endOf — всегда в большую сторону (максимальное значение
интервала)Пример сравнения:
const d = dayjs('2026-05-22T10:15:00');
d.startOf('day'); // 00:00:00.000
d.endOf('day'); // 23:59:59.999
Эти методы часто используются вместе для создания диапазонов.
Один из наиболее распространённых сценариев — построение диапазона для фильтрации данных:
const start = dayjs().startOf('month');
const end = dayjs().endOf('month');
Такой диапазон используется для выборки записей, созданных в текущем месяце.
Пример логики фильтрации:
records.filter(record => {
const date = dayjs(record.createdAt);
return date.isAfter(start) && date.isBefore(end);
});
При использовании week важно учитывать локаль:
dayjs.locale('en'); // неделя начинается с воскресенья
dayjs().startOf('week');
dayjs.locale('ru'); // неделя начинается с понедельника
dayjs().startOf('week');
Это влияет на смещение границ недели и может менять результат на несколько дней.
Метод endOf устанавливает максимальное значение с
точностью до миллисекунд (.999). Это важно при сравнении
дат:
const end = dayjs().endOf('day');
end.millisecond(); // 999
При работе с базами данных иногда требуется учитывать, что некоторые системы используют секунды, а не миллисекунды, что может приводить к пограничным ошибкам.
Оба метода корректно работают в цепочках:
dayjs('2026-05-22')
.add(1, 'month')
.startOf('month')
.add(2, 'day');
Каждый шаг возвращает новый объект, что позволяет строить предсказуемые последовательности преобразований дат.
При подключении расширений Day.js поведение временных границ может дополняться:
utc — приводит вычисления к UTC-времениtimezone — учитывает смещения часовых поясовПример с UTC:
dayjs.utc('2026-05-22').startOf('day');
Здесь начало дня вычисляется уже в контексте UTC, а не локального времени.
Одной из распространённых проблем является неверное понимание границ включительности:
startOf('day') — всегда включаетсяendOf('day') — часто используется как верхняя граница,
но при сравнении с < может исключатьсяПример ошибки:
date.isBefore(dayjs().endOf('day'));
Если сравнение строгое, некоторые значения на границе могут быть исключены.
Другая ошибка связана с ожиданием мутации исходного объекта, что противоречит архитектуре Day.js:
const d = dayjs();
d.startOf('month'); // результат не изменяет d
Методы активно используются в:
Типичный пример агрегации:
const todayStart = dayjs().startOf('day');
const todayEnd = dayjs().endOf('day');
events.filter(e =>
dayjs(e.timestamp).isBetween(todayStart, todayEnd, null, '[]')
);
Такие конструкции позволяют стандартизировать временную логику независимо от источника данных.