mirror of
https://github.com/multipleof4/lynchmark.git
synced 2026-01-14 16:47:55 +00:00
52 lines
1.8 KiB
JavaScript
52 lines
1.8 KiB
JavaScript
const findAvailableSlots = async (calA, calB, constraints) => {
|
|
const { DateTime: D } = await import('https://cdn.jsdelivr.net/npm/luxon@3.4.4/+esm');
|
|
const { durationMinutes: dur, searchRange: rng, workHours: wh } = constraints;
|
|
|
|
const utc = { zone: 'utc' };
|
|
const parse = s => D.fromISO(s, utc);
|
|
const durMs = dur * 60000;
|
|
|
|
const busy = [...calA, ...calB]
|
|
.map(x => ({ s: parse(x.start).valueOf(), e: parse(x.end).valueOf() }))
|
|
.sort((a, b) => a.s - b.s)
|
|
.reduce((acc, cur) => {
|
|
const last = acc.at(-1);
|
|
if (last && cur.s <= last.e) last.e = Math.max(last.e, cur.e);
|
|
else acc.push(cur);
|
|
return acc;
|
|
}, []);
|
|
|
|
const slots = [];
|
|
const rangeStart = parse(rng.start).valueOf();
|
|
const rangeEnd = parse(rng.end).valueOf();
|
|
const [wsH, wsM] = wh.start.split(':').map(Number);
|
|
const [weH, weM] = wh.end.split(':').map(Number);
|
|
|
|
let currDay = parse(rng.start).startOf('day');
|
|
|
|
while (currDay.valueOf() < rangeEnd) {
|
|
const wStart = Math.max(currDay.set({ hour: wsH, minute: wsM }).valueOf(), rangeStart);
|
|
const wEnd = Math.min(currDay.set({ hour: weH, minute: weM }).valueOf(), rangeEnd);
|
|
|
|
if (wStart < wEnd) {
|
|
let ptr = wStart;
|
|
for (const b of busy) {
|
|
if (b.e <= ptr) continue;
|
|
if (b.s >= wEnd) break;
|
|
while (ptr + durMs <= b.s) {
|
|
slots.push({ start: D.fromMillis(ptr, utc).toISO(), end: D.fromMillis(ptr + durMs, utc).toISO() });
|
|
ptr += durMs;
|
|
}
|
|
ptr = Math.max(ptr, b.e);
|
|
}
|
|
while (ptr + durMs <= wEnd) {
|
|
slots.push({ start: D.fromMillis(ptr, utc).toISO(), end: D.fromMillis(ptr + durMs, utc).toISO() });
|
|
ptr += durMs;
|
|
}
|
|
}
|
|
currDay = currDay.plus({ days: 1 });
|
|
}
|
|
|
|
return slots;
|
|
};
|
|
export default findAvailableSlots; |