В библиотеке Luxon объект Duration используется для
представления промежутков времени в абстрактной форме: часы, минуты,
секунды, дни и другие единицы могут сосуществовать одновременно. При
этом значения внутри Duration не всегда находятся в «человеческом» виде
— например, 90 минут могут храниться как { minutes: 90 }, а
не как { hours: 1, minutes: 30 }.
Для управления представлением и перераспределением единиц используется метод shiftTo, который позволяет преобразовать длительность к заданному набору единиц с автоматической нормализацией.
Метод shiftTo перераспределяет (перекладывает) значения Duration между единицами времени так, чтобы итоговый объект содержал только указанные единицы.
Ключевая особенность:
Если исходная длительность содержит больше единиц, чем указано в shiftTo, лишние значения «спускаются» в младшие единицы.
Duration.shiftTo(...units)
Параметры:
units — список строковых идентификаторов единиц времени
("hours", "minutes", "seconds" и
т.д.)Возвращаемое значение:
Durationimport { Duration } from "luxon";
const d = Duration.fromObject({ hours: 1, minutes: 90 });
const shifted = d.shiftTo("hours", "minutes");
console.log(shifted.toObject());
Результат:
{ hours: 2, minutes: 30 }
Объяснение:
Если единица не указана в shiftTo, она не сохраняется явно, но её вклад перераспределяется в оставшиеся единицы.
const d = Duration.fromObject({ hours: 1, minutes: 90 });
const shifted = d.shiftTo("minutes");
console.log(shifted.toObject());
Результат:
{ minutes: 150 }
Здесь всё выражается только в минутах, без сохранения часов как отдельной сущности.
shiftTo особенно полезен при работе с составными длительностями:
const d = Duration.fromObject({
days: 1,
hours: 5,
minutes: 120
});
const normalized = d.shiftTo("days", "hours", "minutes");
console.log(normalized.toObject());
Результат:
{ days: 1, hours: 7, minutes: 0 }
Пояснение:
Внутри Luxon существует также нормализация Duration, но она отличается по смыслу:
const d = Duration.fromObject({ minutes: 90 });
console.log(d.normalize().toObject());
console.log(d.shiftTo("hours", "minutes").toObject());
Результаты могут совпадать, но поведение становится различным при более сложных структурах.
Порядок единиц в shiftTo имеет значение с точки зрения представления результата.
const d = Duration.fromObject({ seconds: 3661 });
console.log(d.shiftTo("hours", "minutes", "seconds").toObject());
Результат:
{ hours: 1, minutes: 1, seconds: 1 }
Если изменить порядок:
console.log(d.shiftTo("seconds", "minutes", "hours").toObject());
Результат будет выражен иначе:
{ seconds: 3661 }
Первая указанная единица становится основной формой хранения.
shiftTo работает с целыми и дробными значениями, но перераспределение может приводить к изменению представления дробных частей.
const d = Duration.fromObject({ seconds: 90.5 });
const shifted = d.shiftTo("minutes", "seconds");
console.log(shifted.toObject());
Результат:
{ minutes: 1, seconds: 30.5 }
Дробная часть сохраняется в младшей единице.
При обработке массивов длительностей часто требуется привести значения к единому формату.
const durations = [
Duration.fromObject({ hours: 1, minutes: 30 }),
Duration.fromObject({ minutes: 200 }),
Duration.fromObject({ seconds: 7200 })
];
const normalized = durations.map(d =>
d.shiftTo("hours", "minutes")
);
normalized.forEach(d => console.log(d.toObject()));
Результат:
{ hours: 1, minutes: 30 }
{ hours: 3, minutes: 20 }
{ hours: 2, minutes: 0 }
shiftTo часто используется в цепочке преобразований Duration:
const result = Duration
.fromObject({ minutes: 125 })
.shiftTo("hours", "minutes")
.mapUnits(x => x * 2);
console.log(result.toObject());
После shiftTo структура становится предсказуемой, что упрощает дальнейшие операции.
shiftTo может возвращать единицы с нулевыми значениями, если они явно указаны:
const d = Duration.fromObject({ seconds: 3600 });
console.log(d.shiftTo("hours", "minutes").toObject());
Результат:
{ hours: 1, minutes: 0 }
Нулевые значения сохраняются, если соответствующая единица присутствует в списке.
После применения shiftTo:
toObject, toISO, toHuman)const d = Duration.fromObject({ minutes: 90 });
const shifted = d.shiftTo("hours", "minutes");
console.log(shifted.toISO());
Результат:
PT1H30M
shiftTo не ограничивается стандартным набором:
const d = Duration.fromObject({
days: 400,
hours: 10
});
console.log(d.shiftTo("years", "months", "days").toObject());
Результат будет зависеть от календарной модели Luxon, где месяцы и годы считаются приблизительно через фиксированные коэффициенты.
shiftTo часто применяется в сценариях:
При этом ключевым эффектом является получение стабильного формата данных без ручной переработки единиц времени.
const a = Duration.fromObject({ minutes: 60 });
const b = Duration.fromObject({ hours: 1 });
console.log(a.shiftTo("hours", "minutes").toObject());
console.log(b.shiftTo("hours", "minutes").toObject());
Оба результата приводятся к единой структуре:
{ hours: 1, minutes: 0 }
{ hours: 1, minutes: 0 }
Даже при различном исходном представлении итоговая форма совпадает, что делает shiftTo инструментом нормализации данных.