mirror of
https://github.com/multipleof4/lynchmark.git
synced 2026-01-14 08:37:56 +00:00
46 lines
1.6 KiB
JavaScript
46 lines
1.6 KiB
JavaScript
const findAvailableSlots = async (calA, calB, { durationMinutes: dur, searchRange: rng, workHours: wh }) => {
|
|
const { DateTime: D, Interval: I } = await import('https://esm.sh/luxon@3.4.4');
|
|
const utc = { zone: 'utc' };
|
|
const parse = t => D.fromISO(t, utc);
|
|
|
|
const busy = [...calA, ...calB]
|
|
.map(s => I.fromDateTimes(parse(s.start), parse(s.end)))
|
|
.filter(i => i.isValid)
|
|
.sort((a, b) => a.start - b.start)
|
|
.reduce((acc, cur) => {
|
|
const last = acc.at(-1);
|
|
return (last && last.end >= cur.start)
|
|
? (acc[acc.length - 1] = last.union(cur), acc)
|
|
: [...acc, cur];
|
|
}, []);
|
|
|
|
const searchI = I.fromDateTimes(parse(rng.start), parse(rng.end));
|
|
const [sH, sM] = wh.start.split(':');
|
|
const [eH, eM] = wh.end.split(':');
|
|
const slots = [];
|
|
|
|
let day = searchI.start.startOf('day');
|
|
while (day < searchI.end) {
|
|
const wStart = day.set({ hour: sH, minute: sM });
|
|
const wEnd = day.set({ hour: eH, minute: eM });
|
|
const workI = I.fromDateTimes(wStart, wEnd).intersection(searchI);
|
|
|
|
if (workI?.isValid) {
|
|
let cur = workI.start;
|
|
while (cur.plus({ minutes: dur }) <= workI.end) {
|
|
const slotI = I.after(cur, { minutes: dur });
|
|
const clash = busy.find(b => b.overlaps(slotI));
|
|
|
|
if (clash) {
|
|
cur = clash.end > cur ? clash.end : cur.plus({ minutes: 1 });
|
|
} else {
|
|
slots.push({ start: slotI.start.toISO(), end: slotI.end.toISO() });
|
|
cur = slotI.end;
|
|
}
|
|
}
|
|
}
|
|
day = day.plus({ days: 1 });
|
|
}
|
|
return slots;
|
|
};
|
|
export default findAvailableSlots; |