I am migrating from Momentjs to Luxon. I allow users to pick a number of hours that a task will take. When we save this value, I'd like it to normalize. So if a task takes 90 hours, I would prefer if we stored 3 days and 18 hours. I store the ISO Duration String so I'd like to convert PT90H to P3DT18H... of course with any given value.
I have tried Luxon's normalize
function, I tried to call it like so:
const duration = Duration.fromObject({ hours: 90 });
duration.normalize().toISO();
However, normalize
does not seem to do anything to the result. I still get PT90H. Is there a built in way to do this with Luxon?
Durtation.normalize()
won't add properties to the Duration object so you need to supply the units you want it to normalize to. (This is odd to me, but provides implicit control over outcome).
normalize() – Reduce this Duration to its canonical representation in its current units.
const duration = Duration
.fromObject({ days: 0, hours: 90 })
.normalize()
.toISO();
console.log(duration);
<script src="https://cdnjs.cloudflare.com/ajax/libs/luxon/2.2.0/luxon.min.js"></script>
<script>const { Duration } = luxon;</script>
Alternatively you can use Duration.shiftTo()
to explicitly force the duration into specific units.
const duration = Duration
.fromObject({hours: 90 })
.shiftTo('days', 'hours')
.toISO();
console.log(duration);
<script src="https://cdnjs.cloudflare.com/ajax/libs/luxon/2.2.0/luxon.min.js"></script>
<script>const { Duration } = luxon;</script>
If you know you will always want to normalize into all units you could declare a utility to return a Duration object initialized with all units.
function createDuration(duration) {
return Duration.fromObject(
Object.assign(
{ years: 0, months: 0, weeks: 0, days: 0, hours: 0, minutes: 0, seconds: 0, milliseconds: 0 },
duration
)
);
}
const duration = createDuration({ hours: 90, minutes: 3004 }).normalize().toISO();
console.log(duration);
<script src="https://cdnjs.cloudflare.com/ajax/libs/luxon/2.2.0/luxon.min.js"></script>
<script>const { Duration } = luxon;</script>