Duration.normalize() only normalizes on existing keys.
See original GitHub issueEDIT
This was a misunderstanding on my part. The functionality is such that it only normalizes with respect to the provided keys. I thought that these two would give the same result.
const a = luxon.Duration.fromObject({ milliseconds: 1001 }).normalize();
const b = luxon.Duration.fromObject({ seconds: 0, milliseconds: 1001 }).normalize();
console.log('Test - (a) seconds', a.seconds); // gives 0
console.log('Test - (a) milliseconds', a.milliseconds); // gives 1001
console.log('Test - (b) seconds', b.seconds); // gives 1
console.log('Test - (b) milliseconds', b.milliseconds); // gives 1
Perhaps the documentation should be more explicit about this?
ORIGINAL
Title: Chaining Duration.plus() with normalize() results in normalize() not doing anything
Specifically, if you set a value to more than it’s normalized max, it will correctly transform it into the other units. However, when using plus()
, if the sum of any field goes above it’s normalized value, normalize() doesn’t touch it.
Here are some test cases highlighting this issue.
const luxon = require('luxon');
{
const a = luxon.Duration.fromObject({ years: 12019 });
const b = luxon.Duration.fromObject({ months: 13 });
const c = luxon.Duration.fromObject({ days: 366 });
const d = luxon.Duration.fromObject({ hours: 25 });
const e = luxon.Duration.fromObject({ minutes: 61 });
const f = luxon.Duration.fromObject({ seconds: 61 });
const g = luxon.Duration.fromObject({ milliseconds: 1001 });
const h = a.plus(b).plus(c).plus(d).plus(e).plus(f).plus(g).normalize()
console.log('Test A - years', h.years); // gives 12021
console.log('Test A - months', h.months); // gives 1
console.log('Test A - days', h.days); // gives 7
console.log('Test A - hours', h.hours); // gives 2
console.log('Test A - minutes', h.minutes); // gives 2
console.log('Test A - seconds', h.seconds); // gives 2
console.log('Test A - milliseconds', h.milliseconds); // gives 1
}
{
const a = luxon.Duration.fromObject({ months: 6 });
const b = luxon.Duration.fromObject({ months: 7 });
const c = a.plus(b).normalize();
console.log('Test B - years', c.years); // gives 0
console.log('Test B - months', c.months); // gives 13
}
{
const a = luxon.Duration.fromObject({ days: 200 });
const b = luxon.Duration.fromObject({ days: 166 });
const c = a.plus(b).normalize();
console.log('Test C - years', c.years); // gives 0
console.log('Test C - days', c.days); // gives 366
}
{
const a = luxon.Duration.fromObject({ hours: 20 });
const b = luxon.Duration.fromObject({ hours: 5 });
const c = a.plus(b).normalize();
console.log('Test D - days', c.days); // gives 0
console.log('Test D - hours', c.hours); // gives 25
}
{
const a = luxon.Duration.fromObject({ minutes: 43 });
const b = luxon.Duration.fromObject({ minutes: 18 });
const c = a.plus(b).normalize();
console.log('Test E - hours', c.hours); // gives 0
console.log('Test E - minutes', c.minutes); // gives 61
}
{
const a = luxon.Duration.fromObject({ seconds: 43 });
const b = luxon.Duration.fromObject({ seconds: 18 });
const c = a.plus(b).normalize();
console.log('Test F - minutes', c.minutes); // gives 0
console.log('Test F - seconds', c.seconds); // gives 61
}
{
const a = luxon.Duration.fromObject({ milliseconds: 500 });
const b = luxon.Duration.fromObject({ milliseconds: 501 });
const c = a.plus(b).normalize();
console.log('Test G - seconds', c.seconds); // gives 0
console.log('Test G - milliseconds', c.milliseconds); // gives 1001
}
{ // Also seems to be the case for minus
const a = luxon.Duration.fromObject({ years: 12019 });
const b = luxon.Duration.fromObject({ months: 1 });
const c = luxon.Duration.fromObject({ days: 1 });
const d = luxon.Duration.fromObject({ hours: 1 });
const e = luxon.Duration.fromObject({ minutes: 1 });
const f = luxon.Duration.fromObject({ seconds: 1 });
const g = luxon.Duration.fromObject({ milliseconds: 1 });
const h = a.minus(b).minus(c).minus(d).minus(e).minus(f).minus(g).normalize()
console.log('Test H - years', h.years); // gives 12018
console.log('Test H - months', h.months); // gives 11
console.log('Test H - days', h.days); // gives -1
console.log('Test H - hours', h.hours); // gives -1
console.log('Test H - minutes', h.minutes); // gives -1
console.log('Test H - seconds', h.seconds); // gives -1
console.log('Test H - milliseconds', h.milliseconds); // gives -1
}
I’ve looked at the source code for the plus
/minus
/normalize
functions, but I’m unfamiliar with this code base, so I don’t know what could be causing it. I would only be speculating if I tried.
If I were to speculate, I would suspect https://github.com/moment/luxon/blob/master/src/duration.js#L233 . i.e. that the fromObject
does some pre-normalization on creation that the new Duration object created during clone
does not.
Issue Analytics
- State:
- Created 5 years ago
- Reactions:9
- Comments:6 (1 by maintainers)
For you finding this when being confused about
DateTime.diff
, provide a list of units as second argument as a hint to.diff
.Intuition for dates/times is contextual and tricky. That’s why this library exists.
So, I think that having an optional parameter to explicitly declare which keys to normalise with would be good for two reasons.
Being an optional parameter, it wouldn’t be a breaking change, either.