Wenn Google Kalender-API, dauert es:Suche nächste freie Stunde gegeben Reihe von geschäftigen Zeiten
start
(Epochenzeit) end
(Epochenzeit) timeZone
(dh America/Los_Angeles
)
Die Antwort eine ist Array genannt busy
, welche Objekte wie { start <Date>, end<Date>}
Mein Ziel enthält: finden Sie die nächste freie Stunde zwischen start
und end
.
mit den folgenden Einschränkungen:
- in Werktagen (Montag-Freitag) sein muss
- muss in der Arbeitszeit sein (9.00 Uhr bis 17.00 Uhr)
Dies ist, was ich versucht habe, :
- manuell mehr
busy
Objekte für jeden Tag von 9.00 bis 17.00 Uhr erstellen
- manuell mehr
busy
Objekte für Samstag und Sonntag - merge erstellen alle
busy
zusammen Blöcke so wird es
nun die entgegengesetzten Zeiten, die die free
Zeiten sind nimm keine Kreuzung sein.
Das erste freie Zeitobjekt ({start <Date>,end <Date>}
), für die start
- end
> = 1 hour
die nächste freie Stunde. Falls keine der free
Objekte größer als 1 Stunde ist, gibt es keine freie Stunde zwischen start
und end
Dieser Sound auch für dieses Problem viel, Ich mag würde hören Vorschläge
so weit
Dieser ist mein Code (in Betrieb):
const moment=require('moment-timezone');
const chrono = require('chrono-node');
const ms = require('ms');
/**
* given start and end dates and list of busy dates, return the next free hour
* @param {Number} start - epoch date
* @param {Number} end - epoch date
* @param {String} timeZone - to get the actual date data (like day of week for the start,end dates)
* @param {Array} epochBusyRanges - [{start,end},{start,end}...] all epoch dates
* @return {Number|null} if number, this is the start of the next available free hour
*/
function nextAvailableHour(start, end, timeZone, epochBusyRanges) {
//SOME SETTINGS
const minMeetingTimeMS = ms('1 hour');
const startWorkDayAM = 9;
const endWorkDayPM = 5;
const weekendStartDateTime = 'friday 23:59';
const weekendEndDateTime = 'sunday 23:59';
//manually put "busy" hours (work days (Monday to Friday) + work hours (9 to 17) are free,else busy)
const momentStart = moment.tz(start, timeZone);
const momentEnd = moment.tz(end, timeZone);
let next5pm = moment.tz(chrono.parseDate(`${endWorkDayPM}pm`, momentStart), timeZone);
let next9am;
while (Number(next5pm) < Number(momentEnd)) {
next9am = moment.tz(chrono.parseDate(`tomorrow ${startWorkDayAM}am`, next5pm), timeZone);
epochBusyRanges.push({start: Number(next5pm), end: Number(next9am)});
next5pm = moment.tz(chrono.parseDate(`${endWorkDayPM}pm`, next9am), timeZone);
}
//we need to put also yesterday's 5pm-9am is the start is before 9am, otherwise it will make a "false" free time..
if (momentStart.hour() < startWorkDayAM) {
const yesterday5pm = moment.tz(chrono.parseDate(`yesterday ${endWorkDayPM}pm`, momentStart), timeZone);
const today9am = moment.tz(chrono.parseDate(`tomorrow ${startWorkDayAM}am`, yesterday5pm), timeZone);
epochBusyRanges.push({start: Number(yesterday5pm), end: Number(today9am)});
}
//insert weekends manually
let nextWeekendStart = moment.tz(chrono.parseDate(`this ${weekendStartDateTime}`, momentStart), timeZone);
let nextWeekendEnd;
while (Number(nextWeekendStart) < Number(momentEnd)) {
nextWeekendEnd = moment.tz(chrono.parseDate(`next ${weekendEndDateTime}`, nextWeekendStart), timeZone);
epochBusyRanges.push({start: Number(nextWeekendStart), end: Number(nextWeekendEnd)});
nextWeekendStart = moment.tz(chrono.parseDate(`this ${weekendStartDateTime}`, nextWeekendEnd), timeZone);
}
//we need also last weekend if we happen to be inside it.
if (momentStart.day() === 0 || momentStart.day() === 6) {
const lastWeekendStart = moment.tz(chrono.parseDate(weekendStartDateTime, momentStart), timeZone);
const lastWeekendEnd = moment.tz(chrono.parseDate(`next ${weekendEndDateTime}`, lastWeekendStart), timeZone);
epochBusyRanges.push({start: Number(lastWeekendStart), end: Number(lastWeekendEnd)});
}
//sort the times
epochBusyRanges.sort((o1, o2) => o1.start > o2.start);
//merge busy blocks
epochBusyRanges = merge(epochBusyRanges.map(o => [o.start, o.end]));
//map again to our format
epochBusyRanges = epochBusyRanges.map(o => {return {start: o[0], end: o[1]}});
//find next hour
for (let i = 0; i < epochBusyRanges.length; i++) {
const _start = i === 0 ? start : epochBusyRanges[i - 1].end;
const _end = epochBusyRanges[i].start;
if ((_end - _start) >= minMeetingTimeMS) {
return _start;
}
}
//maybe there is a free time after the last busy block
if (epochBusyRanges.length > 0) {
const _start = epochBusyRanges[epochBusyRanges.length - 1].end;
if ((end - _start) >= minMeetingTimeMS) {
return _start
}
}
//not busy time at all. so just check for the duration between start and end
if (epochBusyRanges.length === 0) {
if ((end - start) >= minMeetingTimeMS) {
return start;
}
}
return null;
}
//helper function: given [[10,20],[12,30],[40,50]] --- > [[10,30],[40,50]]
function merge(arr) {
// copy and sort the array
const result = arr.slice().sort((a, b) => a[0] > b[0]);
let i = 0;
while (i < result.length - 1) {
const current = result[i],
next = result[i + 1];
// check if there is an overlapping
if (current[1] >= next[0]) {
current[1] = Math.max(current[1], next[1]);
// remove next
result.splice(i + 1, 1);
} else {
// move to next
i++;
}
}
return result;
}
Dank der verfügbaren Arithmetik, können Sie grobe Schritte des Algorithmus zur Verfügung stellen? – YardenST