Files
lynchmark/tests/7_scheduler/outputs/anthropic_claude-sonnet-4.5 TEMP_0.7.js
2025-11-14 03:31:28 +00:00

81 lines
2.5 KiB
JavaScript

async function findAvailableSlots(cal1, cal2, constraints) {
const { parse, format, addMinutes, isWithinInterval, isBefore, isAfter, startOfDay, setHours, setMinutes } = await import('https://cdn.jsdelivr.net/npm/date-fns@3.0.0/+esm');
const { durationMinutes, searchRange, workHours } = constraints;
const duration = durationMinutes;
const parseTime = (dateStr) => parse(dateStr, "yyyy-MM-dd'T'HH:mm:ss.SSSxxx", new Date());
const toISO = (date) => format(date, "yyyy-MM-dd'T'HH:mm:ss.SSSxxx");
const rangeStart = parseTime(searchRange.start);
const rangeEnd = parseTime(searchRange.end);
const [whStart, whEnd] = workHours.start.split(':').map(Number);
const [whEndH, whEndM] = workHours.end.split(':').map(Number);
const allBusy = [...cal1, ...cal2].map(slot => ({
start: parseTime(slot.start),
end: parseTime(slot.end)
})).sort((a, b) => a.start - b.start);
const merged = [];
for (const slot of allBusy) {
if (!merged.length || isBefore(merged[merged.length - 1].end, slot.start)) {
merged.push({ ...slot });
} else {
merged[merged.length - 1].end = isAfter(slot.end, merged[merged.length - 1].end)
? slot.end
: merged[merged.length - 1].end;
}
}
const freePeriods = [];
let current = rangeStart;
for (const busy of merged) {
if (isBefore(current, busy.start)) {
freePeriods.push({ start: current, end: busy.start });
}
current = isAfter(busy.end, current) ? busy.end : current;
}
if (isBefore(current, rangeEnd)) {
freePeriods.push({ start: current, end: rangeEnd });
}
const isInWorkHours = (date) => {
const day = startOfDay(date);
const workStart = setMinutes(setHours(day, whStart), whEnd > 0 ? 0 : 0);
const workEnd = setMinutes(setHours(day, whEndH), whEndM);
return isWithinInterval(date, { start: workStart, end: workEnd });
};
const slots = [];
for (const period of freePeriods) {
let slotStart = period.start;
while (true) {
const slotEnd = addMinutes(slotStart, duration);
if (isAfter(slotEnd, period.end)) break;
if (isInWorkHours(slotStart) && isInWorkHours(slotEnd)) {
const day1 = startOfDay(slotStart);
const day2 = startOfDay(slotEnd);
if (day1.getTime() === day2.getTime()) {
slots.push({
start: toISO(slotStart),
end: toISO(slotEnd)
});
}
}
slotStart = slotEnd;
}
}
return slots;
}
export default findAvailableSlots;