UNPKG

available-slots

Version:

Find available time slots from your daily schedule with configurable chunks & breaks.

102 lines (101 loc) 3.88 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); Object.defineProperty(exports, "default", { enumerable: true, get: function() { return _default; } }); /** * Converts time in HH:MM format to total minutes since midnight. * This makes time calculations and comparisons much easier to work with. */ const timeToMinutes = (time)=>{ const [hours, minutes] = time.split(':').map(Number); return hours * 60 + minutes; }; /** * Ensure proper zero-padding for consistent time string formatting. */ const zeroPadding = (time)=>{ return String(time).padStart(2, '0'); }; /** * Converts total minutes since midnight back to HH:MM time format. */ const minutesToTime = (minutes)=>{ const hours = Math.floor(minutes / 60); const mins = minutes % 60; return `${zeroPadding(hours)}:${zeroPadding(mins)}`; }; /** * Creates a time slot from start time in minutes and duration. * Helper function to reduce duplication in slot creation. */ const createSlot = (startMinutes, slotSize)=>({ start: minutesToTime(startMinutes), end: minutesToTime(startMinutes + slotSize) }); /** * Consolidates overlapping or adjacent busy time periods into single merged slots. * This prevents gaps in the schedule from being incorrectly identified as available * when busy periods actually touch or overlap each other. */ const mergeOverlappingSlots = (slots)=>{ if (slots.length === 0) return []; const sortedSlots = slots.map((slot)=>({ start: timeToMinutes(slot.start), end: timeToMinutes(slot.end) })).sort((a, b)=>a.start - b.start); const merged = [ sortedSlots[0] ]; for(let i = 1, l = sortedSlots.length; i < l; i++){ const current = sortedSlots[i]; const last = merged[merged.length - 1]; if (current.start <= last.end) { last.end = Math.max(last.end, current.end); } else { merged.push(current); } } return merged.map((slot)=>({ start: minutesToTime(slot.start), end: minutesToTime(slot.end) })); }; /** * Finds gaps between busy periods and creates available time slots with proper spacing. * The algorithm walks through the day, fitting slots before each busy period, then * continuing after busy periods end. Break time is added between consecutive available slots. */ const generateAvailableSlots = (mergedBusy, startTime, endTime, slotSize, breakTime)=>{ const available = []; const totalSlotTime = slotSize + breakTime; const busyInMinutes = mergedBusy.map((slot)=>({ start: timeToMinutes(slot.start), end: timeToMinutes(slot.end) })); let currentTime = startTime; for (const busySlot of busyInMinutes){ while(currentTime + slotSize <= busySlot.start){ available.push(createSlot(currentTime, slotSize)); currentTime += totalSlotTime; } currentTime = Math.max(currentTime, busySlot.end); } while(currentTime + slotSize <= endTime){ available.push(createSlot(currentTime, slotSize)); currentTime += totalSlotTime; } return available; }; /** * Main entry point for finding available time slots in a daily schedule. * Processes user options, handles overlapping busy periods, and orchestrates * the slot generation algorithm to return available time periods. */ const slots = (options)=>{ const { busy, slotSize = 30, breakTime = 0, startTime = '08:00', endTime = '18:00' } = options; const startMinutes = timeToMinutes(startTime); const endMinutes = timeToMinutes(endTime); const mergedBusy = mergeOverlappingSlots(busy); return generateAvailableSlots(mergedBusy, startMinutes, endMinutes, slotSize, breakTime); }; const _default = slots; //# sourceMappingURL=index.js.map