function getFirstAvailableTime(now, unavailable, timeSlotSize = 30) {
// Start at the first available timeslot _after_ now.
const start = Math.ceil((minutes(now) + 1) / timeSlotSize) * timeSlotSize;
for (let min = start; min < 1440; min += timeSlotSize) {
if (!unavailable.find(({ start, end }) => (min >= minutes(start) && min <= minutes(end)))) {
return { hour: Math.floor(min / 60), minute: min % 60 };
}
}
}
function minutes( { hour, minute }) {
return hour * 60 + minute;
}
function formatTime({ hour, minute }) {
return [hour, minute].map(n => (n + '').padStart(2, '0')).join(':');
}
function formatSpan({ start, end }) {
return [formatTime(start), formatTime(end)].join(' - ');
}
const inputs = [{ now: { hour: 8, minute: 45 }, unavailable: [{ start: { hour: 7, minute: 0}, end: { hour: 8, minute: 0} } ] },{ now: { hour: 13, minute: 35 }, unavailable: [{ start: { hour: 14, minute: 0}, end: { hour: 15, minute: 0} } ] },{ now: { hour: 11, minute: 0 }, unavailable: [{ start: { hour: 11, minute: 30}, end: { hour: 13, minute: 0} },{ start: { hour: 13, minute: 30}, end: { hour: 14, minute: 0} } ] } ]
console.log('Now'.padEnd(10, ' '), 'Unavailable'.padEnd(32, ' '), 'Next Slot');
for(let input of inputs) {
console.log(formatTime(input.now).padEnd(10, ' '), input.unavailable.map(formatSpan).join(', ').padEnd(32, ' '), formatTime(getFirstAvailableTime(input.now, input.unavailable)))
}
.as-console-wrapper { max-height: 100% !important; }