mirror of
https://github.com/multipleof4/lynchmark.git
synced 2026-01-14 16:47:55 +00:00
59 lines
1.9 KiB
JavaScript
59 lines
1.9 KiB
JavaScript
const findAvailableSlots = async (calA, calB, { durationMinutes, searchRange, workHours }) => {
|
|
const { parseISO, formatISO, addMinutes } = await import('https://cdn.jsdelivr.net/npm/date-fns@3.6.0/+esm');
|
|
|
|
const rangeStart = parseISO(searchRange.start).getTime();
|
|
const rangeEnd = parseISO(searchRange.end).getTime();
|
|
const durationMs = durationMinutes * 60 * 1000;
|
|
|
|
const busy = [...calA, ...calB]
|
|
.map(s => ({ start: parseISO(s.start).getTime(), end: parseISO(s.end).getTime() }))
|
|
.sort((a, b) => a.start - b.start);
|
|
|
|
const merged = [];
|
|
if (busy.length) {
|
|
let curr = busy[0];
|
|
for (const next of busy.slice(1)) {
|
|
if (curr.end >= next.start) {
|
|
curr.end = Math.max(curr.end, next.end);
|
|
} else {
|
|
merged.push(curr);
|
|
curr = next;
|
|
}
|
|
}
|
|
merged.push(curr);
|
|
}
|
|
|
|
const slots = [];
|
|
let now = rangeStart;
|
|
|
|
while (now + durationMs <= rangeEnd) {
|
|
const currentDate = new Date(now);
|
|
const dateStr = currentDate.toISOString().split('T')[0];
|
|
const workStart = parseISO(`${dateStr}T${workHours.start}:00Z`).getTime();
|
|
const workEnd = parseISO(`${dateStr}T${workHours.end}:00Z`).getTime();
|
|
|
|
if (now < workStart) {
|
|
now = workStart;
|
|
continue;
|
|
}
|
|
|
|
if (now + durationMs > workEnd) {
|
|
now = addMinutes(workStart, 24 * 60).getTime();
|
|
continue;
|
|
}
|
|
|
|
const conflict = merged.find(b => now < b.end && (now + durationMs) > b.start);
|
|
|
|
if (conflict) {
|
|
now = conflict.end;
|
|
} else {
|
|
const start = new Date(now);
|
|
const end = new Date(now + durationMs);
|
|
slots.push({ start: formatISO(start), end: formatISO(end) });
|
|
now += durationMs;
|
|
}
|
|
}
|
|
|
|
return slots;
|
|
};
|
|
export default findAvailableSlots; |