const _ = require('lodash'); const parser = s => { const parts = s.split(':'); return parts[0] * 60 + +parts[1] }; const doesOverlap = (slot, booking) => { if (!slot || !booking) { return false; } return (slot[0] <= booking[1] && slot[1] >= booking[0]) || (booking[0] <= slot[1] && booking[1] >= slot[0]); }; const render = t => `${Math.floor(t / 60).toString().padStart(2, '0')}:${(t % 60).toString().padStart(2, '0')}`; const getAvailableTime = (start, end, blocks, duration) => { blocks = blocks.map(b => b.map(parser)); blocks = _.sortBy(blocks, '0'); start = parser(start); end = parser(end); duration = parser(duration); const genBlocks = []; let blockI = 0; for (let i = start; i < end - duration; i++) { const possibleBlock = [i, i + duration - 1]; if (doesOverlap(possibleBlock, blocks[blockI])) { i = blocks[blockI][1]; blockI++; } else { genBlocks.push(possibleBlock); i += (duration - 1); } } return genBlocks.map(b => b.map(render)); }; getAvailableTime('8:00', '17:00', [['8:40', '9:20'], ['13:30', '14: 40']], '0:30'); // 08:00,08:29 // 09:21,09:50 // 09:51,10:20 // 10:21,10:50 // 10:51,11:20 // 11:21,11:50 // 11:51,12:20 // 12:21,12:50 // 12:51,13:20 // 14:41,15:10 // 15:11,15:40 // 15:41,16:10 // 16:11,16:40