Skip to content

Instantly share code, notes, and snippets.

@clindsey
Created December 9, 2016 07:18
Show Gist options
  • Save clindsey/71136bd46c83cdcad1139ee2cf998a39 to your computer and use it in GitHub Desktop.
Save clindsey/71136bd46c83cdcad1139ee2cf998a39 to your computer and use it in GitHub Desktop.
schedule-logic-1.0.0
const scheduleLogic = {
calculateTimeRange: (settings, targetDate, startTime, endTime) => {
const initialTime = scheduleLogic.calculateFirstTime(settings, targetDate);
const startTimes = scheduleLogic.calculateStartTimes(settings, initialTime);
let newStartTime = targetDate.clone().hours(startTime.hours()).minutes(startTime.minutes());
let findResult = startTimes.find(time => time.toISOString() === newStartTime.toISOString());
if (!findResult) {
newStartTime = startTimes[0];
}
const endTimes = scheduleLogic.calculateEndTimes(settings, initialTime, newStartTime);
let newEndTime = targetDate.clone().hours(endTime.hours()).minutes(endTime.minutes());
if (newEndTime.hours() < moment(settings.endTime, 'HHmm').hours()) {
newEndTime.add(1, 'day');
}
findResult = endTimes.find(time => time.toISOString() === newEndTime.toISOString());
if (!findResult) {
newEndTime = endTimes[0]
}
return {
endTime: newEndTime,
endTimes,
startTime: newStartTime,
startTimes
};
},
calculateFirstTime: (settings, targetDate) => {
const {
endTime,
minLeadTime,
timeIncrement
} = settings;
const startTime = moment(settings.startTime, 'HHmm');
const now = moment();
let hours = startTime.hours();
let minutes = startTime.minutes();
const firstTime = targetDate.clone().set({hours, minutes});
if (firstTime.isBefore(now)) { // this handles the today case
now.add(minLeadTime, 'minutes');
const minutes = now.minutes();
const minuteDelta = (Math.ceil(minutes / timeIncrement) * timeIncrement) - minutes;
const todayFirstTime = now.add(minuteDelta, 'minutes').seconds(0).milliseconds(0);
// refactor, handle cases after 9:30, it generates too many options and they're out of valid range
return todayFirstTime;
}
return firstTime;
},
calculateStartTimes: (settings, initialTime) => {
const {
endTime,
maxDuration,
minDuration,
timeIncrement
} = settings;
const latestTime = moment(endTime, 'HHmm').subtract(minDuration, 'minutes');
if ((maxDuration / timeIncrement) % 2) { // hopefully this prevents an infinite loops in thie `while` below
throw new Error('Invalid settings: `maxDuration` must be evenly divisable by `timeIncrement`');
}
const startTimes = [
initialTime.clone()
];
while (true) { // eslint-disable-line no-constant-condition
const time = startTimes[startTimes.length - 1].clone();
startTimes.push(time.add(timeIncrement, 'minutes'));
if (time.format('HHmm') === latestTime.format('HHmm')) {
break;
}
}
return startTimes;
},
calculateEndTimes: (settings, initialTime, startTime) => {
const {
endTime,
minDuration,
maxDuration,
timeIncrement
} = settings;
const earliestTime = startTime.clone().add(minDuration, 'minutes');
let remainingTime = maxDuration;
const endTimes = [
earliestTime.clone()
];
while (remainingTime) {
remainingTime -= timeIncrement;
const time = endTimes[endTimes.length - 1].clone();
if (time.format('HHmm') === endTime) {
break;
}
endTimes.push(time.add(timeIncrement, 'minutes'));
}
return endTimes;
},
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment