Docs: Update benchmark results

This commit is contained in:
github-actions[bot]
2025-11-18 23:31:52 +00:00
parent 341252fec1
commit 5855cf8a6f
77 changed files with 972 additions and 1051 deletions

View File

@@ -1,58 +1,74 @@
async function findAvailableSlots(calendar1, calendar2, constraints) {
const {
parseISO, addMinutes, formatISO, max, setHours, setMinutes,
setSeconds, setMilliseconds, startOfDay, endOfDay, eachDayOfInterval,
} = await import('https://cdn.jsdelivr.net/npm/date-fns@2/esm/index.js');
parseISO, addMinutes, addDays, max, isBefore, isAfter, startOfDay,
} = await import('https://cdn.jsdelivr.net/npm/date-fns@3.6.0/esm/index.js');
const { durationMinutes: duration, searchRange, workHours } = constraints;
const { durationMinutes, searchRange, workHours } = constraints;
const searchStart = parseISO(searchRange.start);
const searchEnd = parseISO(searchRange.end);
const [workStartH, workStartM] = workHours.start.split(':').map(Number);
const [workEndH, workEndM] = workHours.end.split(':').map(Number);
const setTime = (date, h, m) =>
setMilliseconds(setSeconds(setMinutes(setHours(date, h), m), 0), 0);
const busySlots = [...calendar1, ...calendar2].map(({ start, end }) => ({
start: parseISO(start),
end: parseISO(end),
}));
const nonWorkSlots = eachDayOfInterval({ start: searchStart, end: searchEnd })
.flatMap(day => [
{ start: startOfDay(day), end: setTime(day, workStartH, workStartM) },
{ start: setTime(day, workEndH, workEndM), end: endOfDay(day) }
]);
const allUnavailable = [...busySlots, ...nonWorkSlots]
const busySlots = [...calendar1, ...calendar2]
.map(slot => ({ start: parseISO(slot.start), end: parseISO(slot.end) }))
.sort((a, b) => a.start - b.start);
const merged = allUnavailable.reduce((acc, current) => {
const mergedBusy = busySlots.reduce((acc, current) => {
const last = acc.at(-1);
if (last && current.start <= last.end) {
last.end = max(last.end, current.end);
if (last && isBefore(current.start, last.end)) {
last.end = max([last.end, current.end]);
} else {
acc.push({ ...current });
}
return acc;
}, []);
const availableSlots = [];
const freeIntervals = [];
let cursor = searchStart;
[...merged, { start: searchEnd, end: searchEnd }].forEach(block => {
let slotStart = cursor;
while (addMinutes(slotStart, duration) <= block.start) {
const slotEnd = addMinutes(slotStart, duration);
availableSlots.push({ start: slotStart, end: slotEnd });
slotStart = slotEnd;
mergedBusy.forEach(busy => {
if (isBefore(cursor, busy.start)) {
freeIntervals.push({ start: cursor, end: busy.start });
}
cursor = max(cursor, block.end);
cursor = max([cursor, busy.end]);
});
return availableSlots.map(({ start, end }) => ({
start: formatISO(start),
end: formatISO(end),
if (isBefore(cursor, searchEnd)) {
freeIntervals.push({ start: cursor, end: searchEnd });
}
const availableSlots = freeIntervals.flatMap(gap => {
const slotsInGap = [];
let slotCursor = gap.start;
while (isBefore(slotCursor, gap.end)) {
const day = startOfDay(slotCursor);
const workDayStart = new Date(day);
workDayStart.setUTCHours(workStartH, workStartM, 0, 0);
const workDayEnd = new Date(day);
workDayEnd.setUTCHours(workEndH, workEndM, 0, 0);
const slotStart = max([slotCursor, workDayStart]);
const slotEnd = addMinutes(slotStart, durationMinutes);
const canFit = !isAfter(slotEnd, workDayEnd) && !isAfter(slotEnd, gap.end);
if (canFit) {
slotsInGap.push({ start: slotStart, end: slotEnd });
slotCursor = slotEnd;
} else {
const nextDayStart = addDays(day, 1);
nextDayStart.setUTCHours(workStartH, workStartM, 0, 0);
slotCursor = nextDayStart;
}
}
return slotsInGap;
});
return availableSlots.map(slot => ({
start: slot.start.toISOString(),
end: slot.end.toISOString(),
}));
}
export default findAvailableSlots;