Метод hasSame

Определяет совпадение двух моментов времени в пределах заданной календарной единицы, используя правила календаря конкретной локали и часового пояса. Сравнение выполняется не по абсолютной разнице в миллисекундах, а по принадлежности к одному и тому же «временнóму контейнеру» — году, месяцу, дню, часу и т.д.


Метод вызывается у экземпляра DateTime и принимает два аргумента:

dt.hasSame(otherDateTime, unit)
  • otherDateTime — второй объект DateTime, с которым выполняется сравнение
  • unit — строка, задающая уровень сравнения

Поддерживаемые единицы измерения

Метод работает с календарными единицами времени:

  • "year" — год
  • "month" — месяц
  • "week" — календарная неделя
  • "day" — день
  • "hour" — час
  • "minute" — минута
  • "second" — секунда
  • "millisecond" — миллисекунда

Каждая следующая единица уточняет гранулярность сравнения: от грубого (год) до максимально точного (миллисекунда).


Базовый принцип работы

Сравнение выполняется по календарным полям, а не по абсолютному времени в UTC. Это означает, что:

  • одинаковые моменты времени в разных зонах могут не считаться равными по дню
  • одинаковые локальные даты считаются совпадающими, даже если UTC-значения различаются

Сравнение по году

import { DateTime } from "luxon";

const a = DateTime.fromISO("2026-01-01T10:00");
const b = DateTime.fromISO("2026-12-31T23:59");

a.hasSame(b, "year"); // true

Оба значения принадлежат одному календарному году.


Сравнение по месяцу

const a = DateTime.fromISO("2026-05-01T00:00");
const b = DateTime.fromISO("2026-05-31T23:59");

a.hasSame(b, "month"); // true

Несмотря на разные дни, месяц совпадает.


Сравнение по дню

const a = DateTime.fromISO("2026-05-23T00:00");
const b = DateTime.fromISO("2026-05-23T23:59");

a.hasSame(b, "day"); // true

Оба значения принадлежат одному календарному дню.


Влияние времени суток

При проверке уровня "day" время игнорируется полностью:

const a = DateTime.fromISO("2026-05-23T08:00");
const b = DateTime.fromISO("2026-05-23T22:00");

a.hasSame(b, "day"); // true

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

const a = DateTime.fromISO("2026-05-23T10:15");
const b = DateTime.fromISO("2026-05-23T10:59");

a.hasSame(b, "hour"); // true

Обе метки времени находятся в одном часовом интервале.


Переход через границу часа

const a = DateTime.fromISO("2026-05-23T10:59");
const b = DateTime.fromISO("2026-05-23T11:00");

a.hasSame(b, "hour"); // false

Несмотря на разницу в одной минуте, час уже другой.


Работа с минутами и секундами

const a = DateTime.fromISO("2026-05-23T10:15:30");
const b = DateTime.fromISO("2026-05-23T10:15:59");

a.hasSame(b, "minute"); // true
a.hasSame(b, "second"); // false

Сравнение по неделе

Неделя определяется календарными правилами (обычно ISO-неделя):

const a = DateTime.fromISO("2026-05-20");
const b = DateTime.fromISO("2026-05-24");

a.hasSame(b, "week"); // true

Если даты попадают в одну и ту же календарную неделю, результат совпадает.


Влияние часового пояса

Ключевая особенность — сравнение выполняется в контексте часового пояса первого объекта.

const a = DateTime.fromISO("2026-05-23T00:30", { zone: "Europe/Paris" });
const b = DateTime.fromISO("2026-05-22T23:30", { zone: "UTC" });

a.hasSame(b, "day");

Результат может быть как true, так и false в зависимости от локального дня a.

Это связано с тем, что календарные поля приводятся к зоне экземпляра, у которого вызывается метод.


Сравнение разных зон на практике

const a = DateTime.fromISO("2026-05-23T01:00", { zone: "Asia/Almaty" });
const b = DateTime.fromISO("2026-05-22T20:00", { zone: "UTC" });

a.hasSame(b, "day");

Значения могут относиться к одному и тому же моменту времени, но разные локальные дни приводят к false.


Отличие от абсолютного сравнения времени

hasSame не эквивалентен проверке разницы в миллисекундах:

  • одинаковое время в UTC может быть разным днём локально
  • разные моменты времени могут попадать в один календарный интервал

Сравнение с преобразованием через startOf

Эквивалентная логика может быть выражена через нормализацию:

a.startOf("day").toMillis() === b.startOf("day").toMillis();

Однако hasSame выполняет эту проверку напрямую и без создания новых объектов.


Поведение при разных единицах

Каждая единица определяет уровень округления:

  • "year" — игнорируются месяц, день и время
  • "month" — игнорируются день и время
  • "day" — игнорируется время
  • "hour" — игнорируются минуты и секунды
  • "minute" — игнорируются секунды и миллисекунды

Пограничные случаи

Переход через полночь

const a = DateTime.fromISO("2026-05-23T23:59");
const b = DateTime.fromISO("2026-05-24T00:00");

a.hasSame(b, "day"); // false

Даже минимальный переход меняет календарный день.


Миллисекунды

const a = DateTime.fromISO("2026-05-23T10:00:00.000");
const b = DateTime.fromISO("2026-05-23T10:00:00.001");

a.hasSame(b, "millisecond"); // false

Любое различие в точности фиксируется.


Поведение с некорректными значениями

Если один из объектов DateTime является невалидным:

const a = DateTime.invalid("error");
const b = DateTime.now();

a.hasSame(b, "day"); // false

Невалидное значение не может быть сопоставлено ни с каким календарным интервалом.


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

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

Логическая модель метода

Внутренне сравнение можно представить как:

  1. преобразование обоих DateTime в одну календарную систему
  2. извлечение полей выбранной единицы
  3. поэлементное сравнение значений
  4. возврат true, если все поля совпали

Важная особенность календарных границ

Календарные единицы не являются равномерными интервалами:

  • месяц может иметь 28, 30 или 31 день
  • неделя зависит от локализации
  • год может быть високосным

Поэтому hasSame работает именно с календарной структурой, а не с фиксированными длительностями.