available-slots
Version:
Find available time slots from your daily schedule with configurable chunks & breaks.
102 lines (101 loc) • 3.88 kB
JavaScript
;
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