Работа с датами почти всегда связана с изменением временных значений:
прибавлением дней, вычислением будущих дат, вычитанием часов, переносом
времени между временными зонами и расчётом интервалов. В библиотеке
Luxon эти операции реализованы через методы plus() и
minus().
Главная особенность Luxon заключается в том, что объекты
DateTime являются неизменяемыми. Любое изменение создаёт
новый объект, не затрагивая исходный.
import { DateTime } from "luxon";
const now = DateTime.now();
const tomorrow = now.plus({ days: 1 });
console.log(now.toISO());
console.log(tomorrow.toISO());
Исходный объект now остаётся прежним.
Метод plus() добавляет к дате или времени указанные
единицы.
const date = DateTime.now();
const result = date.plus({ days: 5 });
console.log(result.toISO());
Объект внутри plus() представляет собой набор единиц
времени.
Luxon поддерживает множество временных единиц:
| Единица | Ключ |
|---|---|
| Миллисекунды | milliseconds |
| Секунды | seconds |
| Минуты | minutes |
| Часы | hours |
| Дни | days |
| Недели | weeks |
| Месяцы | months |
| Кварталы | quarters |
| Годы | years |
Пример:
const result = DateTime.now().plus({
years: 1,
months: 2,
days: 10,
hours: 5
});
const meeting = DateTime.now().plus({
hours: 2,
minutes: 30
});
console.log(meeting.toFormat("HH:mm"));
Методы можно вызывать цепочкой.
const result = DateTime.now()
.plus({ days: 1 })
.plus({ hours: 3 })
.plus({ minutes: 15 });
console.log(result.toISO());
Однако чаще удобнее передавать всё одним объектом.
const result = DateTime.now().plus({
days: 1,
hours: 3,
minutes: 15
});
Метод minus() работает аналогично, но выполняет
вычитание.
const yesterday = DateTime.now().minus({ days: 1 });
console.log(yesterday.toISODate());
const past = DateTime.now().minus({
hours: 6
});
console.log(past.toISO());
const result = DateTime.now().minus({
years: 1,
months: 2,
weeks: 1,
days: 3
});
При работе с месяцами Luxon автоматически корректирует дату.
const date = DateTime.fromISO("2025-01-31");
const result = date.plus({ months: 1 });
console.log(result.toISODate());
Результат:
2025-02-28
Так происходит потому, что в феврале нет 31 числа.
const date = DateTime.fromISO("2024-02-29");
const result = date.plus({ years: 1 });
console.log(result.toISODate());
Результат:
2025-02-28
Luxon корректно учитывает високосные годы.
Методы plus() и minus() фактически могут
выполнять обе операции.
const result = DateTime.now().plus({ days: -5 });
Эквивалентно:
const result = DateTime.now().minus({ days: 5 });
Но для читаемости лучше использовать соответствующий метод.
const date = DateTime.fromObject({
year: 2025,
month: 5,
day: 10,
hour: 12
});
const upd ated = date.plus({
days: 3,
hours: 4
});
console.log(updated.toString());
Операции учитывают временную зону объекта.
const dt = DateTime.now().setZone("Europe/Berlin");
const result = dt.plus({ hours: 5 });
console.log(result.toString());
Если происходит переход между часовыми поясами или летним временем, Luxon корректно пересчитывает итоговое значение.
const dt = DateTime.fromISO(
"2025-03-30T01:30",
{ zone: "Europe/Berlin" }
);
const result = dt.plus({ hours: 1 });
console.log(result.toString());
Во время перехода на летнее время некоторые часы могут отсутствовать. Luxon учитывает это автоматически.
Между добавлением часов и дней существует важная разница.
const dt = DateTime.fromISO(
"2025-03-30T00:00",
{ zone: "Europe/Berlin" }
);
const result = dt.plus({ days: 1 });
const result = dt.plus({ hours: 24 });
Эти операции могут дать разный результат при переходе на летнее или зимнее время.
days изменяет календарную датуhours добавляет точное количество часовДля хранения промежутков времени применяется объект
Duration.
import { Duration } from "luxon";
const duration = Duration.fromObject({
days: 2,
hours: 5
});
const result = DateTime.now().plus(duration);
console.log(result.toISO());
const duration = Duration.fromObject({
hours: 10,
minutes: 45
});
const start = DateTime.now();
const duration = Duration.fromObject({
weeks: 1,
days: 2
});
const end = start.plus(duration);
console.log(end.toISO());
const duration = Duration.fromObject({
months: 3
});
const result = DateTime.now().minus(duration);
Иногда длительность содержит значения, выходящие за пределы диапазона.
const duration = Duration.fromObject({
minutes: 120
});
console.log(duration.toObject());
Нормализация:
const normalized = duration.normalize();
console.log(normalized.toObject());
Результат:
{
hours: 2
}
Luxon поддерживает краткие формы единиц.
const result = DateTime.now().plus({
d: 1,
h: 5
});
Однако рекомендуется использовать полные названия:
{
days: 1,
hours: 5
}
Так код проще поддерживать.
const now = DateTime.now();
const future = now.plus({ days: 7 });
console.log(future > now);
Лучше использовать числовое значение:
console.log(future.toMillis() > now.toMillis());
const createdAt = DateTime.fromISO("2025-01-10");
const daysPassed = DateTime.now()
.diff(createdAt, "days")
.days;
console.log(daysPassed);
let current = DateTime.now();
for (let i = 0; i < 5; i++) {
current = current.plus({ days: 1 });
console.log(current.toISODate());
}
const start = DateTime.fromISO("2025-05-01");
const dates = [];
for (let i = 0; i < 7; i++) {
dates.push(
start.plus({ days: i }).toISODate()
);
}
console.log(dates);
Добавление и вычитание часто используется вместе с
Interval.
import { Interval } from "luxon";
const start = DateTime.now();
const end = start.plus({ hours: 2 });
const interval = Interval.fromDateTimes(start, end);
console.log(interval.length("minutes"));
const now = DateTime.now();
const previousHour = now.minus({ hours: 1 });
const nextHour = now.plus({ hours: 1 });
const date = DateTime.now();
const updated = date.plus({
hours: 3
});
const updated = DateTime.now().plus({
days: 10
});
const nextMonth = DateTime.now()
.plus({ months: 1 })
.startOf("month");
console.log(nextMonth.toISO());
const previousMonthEnd = DateTime.now()
.minus({ months: 1 })
.endOf("month");
console.log(previousMonthEnd.toISO());
const utc = DateTime.utc();
const result = utc.plus({
hours: 12
});
console.log(result.toISO());
const expiresAt = DateTime.now().plus({
minutes: 30
});
console.log(expiresAt.toISO());
Проверка истечения:
const isExpired =
DateTime.now() > expiresAt;
const publication = DateTime.now()
.plus({ days: 7 })
.se t({
hour: 9,
minute: 0
});
console.log(publication.toString());
const start = DateTime.fromISO("2025-05-01");
const deadline = start.plus({
months: 2,
weeks: 1
});
console.log(deadline.toISODate());
Неверное ожидание:
const now = DateTime.now();
now.plus({ days: 1 });
console.log(now.toISO());
now не изменится.
Правильно:
const updated = now.plus({ days: 1 });
.plus({ days: 1 })
и
.plus({ hours: 24 })
не всегда эквивалентны.
DateTime.now().plus({ hours: 2 });
Если зона важна, её необходимо задавать явно:
DateTime.now()
.setZone("Asia/Tokyo")
.plus({ hours: 2 });
Luxon создаёт новый объект при каждой операции.
const updated = date
.plus({ days: 1 })
.plus({ hours: 2 })
.plus({ minutes: 30 });
При большом количестве вычислений лучше объединять изменения:
const updated = date.plus({
days: 1,
hours: 2,
minutes: 30
});