JSFiddle - React, Tailwind, and code Playground
by neonDog
JavaScript
import { isWithinInterval, addDays, addMinutes, isSameDay, setHours, setMinutes, setSeconds } from 'https://esm.run/date-fns';
function nextDayOfWeek(date, dayOfWeek) {
date = new Date(date.getTime());
date.setDate(date.getDate() + (dayOfWeek + 7 - date.getDay()) % 7);
return date;
}
const getNextDesirableDates = function (topTimes, date) {
if (!date) date = new Date();
const desiredTimes = [];
for (let i=0, l=topTimes.length; i < l; i++) {
const time = topTimes[i];
let when = nextDayOfWeek(date, time[0]);
if (isSameDay(date, when)) {
//If this hour is not in the future, must add 7 days (schedule 1 week later)
if (date.getHours() > time[1]) {
when = addDays(when, 7);
}
}
when = setHours(when, time[1]);
when = setMinutes(when, time[2]);
desiredTimes.push(when);
}
return desiredTimes;
};
const findAvailableDate = function(results, desired) {
//Loop desired dates
for (let i=0, l=desired.length; i < l; i++) {
//Can we find one that doesn't conflict with results?
if (results.findIndex(date => isSameDay(date, desired[i])) === -1) {
return desired[i];
}
}
};
const getNextAvailableDate = function(results, topTimes) {
let desiredTimes;
let finalDate;
let lastDate = new Date();
while (!finalDate) { //This will loop forever until it finds a free date
desiredTimes = getNextDesirableDates(topTimes, lastDate).sort((a, b) => a - b);
finalDate = findAvailableDate(results, desiredTimes);
if (!finalDate) {
//If we still have conflicts, we need to get more desired dates. Save the last one we'll use it to page
lastDate = addDays(desiredTimes[desiredTimes.length-1], 1);
}
}
return finalDate;
}
const topTimes = [
[0,1,30], //Sunday
[1,9,20], //Monday
[3,15,44], //Wednesday
[5,12,30] //Friday
];
//Feb 1st Mon
//Feb 2nd Tue
//Feb 3rd Wed
//These are already scheduled times
const results = [new Date('2021-02-01 09:00'), new...