假设您有一系列会议的忙碌时间范围
[{'start':'9:00 AM', 'end':'10:00 AM'},
{'start':'12:00 PM', 'end':'2:00 PM'},
{'start':'5:00 AM', 'end':'7:00 PM'}]
我希望在24小时内获得一系列 AVAILABLE 次,这与上述时间相反。像...
[{'start':'00:00 AM', 'end':'9:00 AM'},
{'start':'10:00 AM', 'end':'12:00 PM'},
{'start':'2:00 PM', 'end':'5:00 PM'},
{'start':'7:00 PM', 'end':'11:59 PM'}]
我尝试过使用moment.js和https://www.npmjs.com/package/moment-range,特别是.subtract()
方法。
我知道类似的stackoverflow问题,但无法找到适用于此格式的问题,在javascript中,使用momentJS和优雅的ES6数组方法解决方案。
答案 0 :(得分:7)
function giveUtc(start) {
var t = moment().format("YYYY-MM-DD")
var t1 = t + " " + start
return moment(t1, "YYYY-MM-DD h:mm A").format()
}
const timeRange = [{
'start': '9:00 AM',
'end': '10:00 AM'
},
{
'start': '12:00 PM',
'end': '2:00 PM'
},
{
'start': '5:00 PM',
'end': '7:00 PM'
},
{
"start": "11:00 AM",
"end": "3:00 PM",
},
{
"start": "6:00 PM",
"end": "9:00 PM",
}]
timeRange.sort((a, b) => {
var utcA = giveUtc(a.start)
var utcB = giveUtc(b.start)
if (utcA < utcB) {
return -1
}
if (utcA > utcB) {
return 1
}
return 0
})
const availableTimeArray = []
let endTimeFarthest = moment(giveUtc("0.00 AM"))
let startTimeMinimum = moment(giveUtc("12.59 PM"))
timeRange.forEach((element, index) => {
let currentEndTime = moment(giveUtc(element.end))
const currentStartTime = moment(giveUtc(element.start))
if (currentStartTime.isBefore(startTimeMinimum)) {
startTimeMinimum = currentStartTime
}
if (currentEndTime.isAfter(endTimeFarthest)) {
endTimeFarthest = currentEndTime
}
/* console.log(startTimeMinimum.format("h:mm A"), endTimeFarthest.format("h:mm A")) */
if (index === timeRange.length - 1) {
if (timeRange.length === 1) {
availableTimeArray.push({
start: "00:00 AM",
end: currentStartTime.format("h:mm A")
})
}
availableTimeArray.push({
//start: currentEndTime.format("h:mm A"),
start: endTimeFarthest.format("h:mm A"),
end: "11.59 PM"
})
} else {
const nextBusyTime = timeRange[index + 1]
const nextStartTime = moment(giveUtc(nextBusyTime.start))
if (index === 0) {
availableTimeArray.push({
start: "00:00 AM",
end: currentStartTime.format("h:mm A")
})
}
let endTimeToCompare = currentEndTime.isBefore(endTimeFarthest) ?
endTimeFarthest :
currentEndTime
if (endTimeToCompare.isBefore(nextStartTime)) {
availableTimeArray.push({
start: endTimeToCompare.format("h:mm A"),
end: nextStartTime.format("h:mm A")
})
}
}
})
console.log(availableTimeArray)
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.5.1/moment.min.js"></script>
I have used utc timestamp to compare between timings and assumed that all the interval belongs to a single day. Some edge case might be missing but you can take the idea. I have made use of greedy algorithm. First sorting all the interval based on the start time. Then iterating through the sorted array to pick correct interval
答案 1 :(得分:1)
我一直在思考这个问题。 简单的循环就足够了
我没有对此进行100%测试,因此可能存在边缘情况。
const busy = [{'start':'9:00 AM', 'end':'10:00 AM'},
{'start':'12:00 PM', 'end':'2:00 PM'},
{'start':'5:00 PM', 'end':'7:00 PM'}];
const last = busy.length-1;
let avail = [];
function norm(t) {
let [,hh,mm,ampm] = /(\d{1,2}):(\d{2}) ([AP]M)/.exec(t);
return {"hh": ampm=="PM"? +hh+12:hh,"mm":mm }
}
function makeUSTime(hh) {
return (hh>12?hh-12:hh)+":00";
}
for (let i=0,j=0;i<busy.length;i++) {
for (;j<=24;j++) {
if (norm(busy[i].start).hh>j) {
avail.push({"start":makeUSTime(j),"end":busy[i].start});
j=norm(busy[i].end).hh;
break;
}
}
}
if (norm(busy[last].end).hh<24) avail.push({"start":busy[last].end,"end":"11:59 PM"});
console.log(avail)
&#13;