I'm using Luxon, and have two dates and an ISO duration. How can I determine if the duration between the two dates is an multiple of the duration with no remainder?
I considered converting to "months" for example and just using Javascript's modulus operator to determine if the remainder is 0, but ISO durations can be very complex, eg "P3Y6M4DT12H30M5S" represents a duration of "three years, six months, four days, twelve hours, thirty minutes, and five seconds".
Interval
s have a splitBy
function that seems promising as it leaves the remainder as the last element in the array it returns, but I'm not sure how to then compare that element to my original duration:
import {DateTime, Duration, Interval} from 'luxon';
const date1: DateTime = DateTime.fromJSDate(new Date('12/20/2022'));
const date2: DateTime = DateTime.fromJSDate(new Date('12/20/2023'));
const duration: Duration = Duration.fromISO('P6M');
const interval: Interval = Interval.fromDateTimes(date1, date2);
const split = interval.splitBy(duration);
const modulusDuration = (split[split.length - 1] as Interval).toDuration();
if (modulusDuration.valueOf() === duration.valueOf()) {
console.log('pass'); // We never get here
} else {
// We get here
console.log(modulusDuration.rescale().toObject()) // {months: 6, days: 3, hours: 1}
console.log(duration.rescale().toObject()) // {months: 6}
console.log('fail');
}
Here's a stackblitz: https://stackblitz.com/edit/typescript-kuwjpg?file=index.ts
How can I determine if multiples of a duration fit neatly between two dates?
Thanks to @RobG's comment I was able to get this working by iteratively adding the duration to the start date and checking if it lands exactly on the end date:
import {DateTime, Duration, Interval} from 'luxon';
const date1: DateTime = DateTime.fromJSDate(new Date('1/20/2022'));
const date2: DateTime = DateTime.fromJSDate(new Date('1/20/2023'));
const duration: Duration = Duration.fromISO('P6M');
let pass = false;
for (let i = date1; i <= date2; i = i.plus(duration)) {
if (i.toMillis() === date2.toMillis()) {
pass = true;
}
}
console.log(pass ? 'pass' : 'fail');