Reputation: 506
The title of this question probably isn't totally appropriate and requires much more explanation. The problem: compare a list (array #1) of all time-slots with a list (array #2) of booked time-slots and return a list of available time-slots.
The arrays:
{
"times": [
{
"start": "2017-05-11T19:00:00.000Z",
"stop": "2017-05-11T19:30:00.000Z"
},
{
"start": "2017-05-11T19:30:00.000Z",
"stop": "2017-05-11T20:00:00.000Z"
},
{
"start": "2017-05-11T20:00:00.000Z",
"stop": "2017-05-11T20:30:00.000Z"
},
{
"start": "2017-05-11T20:30:00.000Z",
"stop": "2017-05-11T21:00:00.000Z"
},
{
"start": "2017-05-11T21:00:00.000Z",
"stop": "2017-05-11T21:30:00.000Z"
},
{
"start": "2017-05-11T21:30:00.000Z",
"stop": "2017-05-11T22:00:00.000Z"
}
],
"booked": [
{
"start": "2017-05-11T19:00:00.000Z",
"stop": "2017-05-11T20:30:00.000Z"
}
]
}
The expected and desired result would be:
{
"start": "2017-05-11T20:30:00.000Z",
"stop": "2017-05-11T21:00:00.000Z"
},
{
"start": "2017-05-11T21:00:00.000Z",
"stop": "2017-05-11T21:30:00.000Z"
},
{
"start": "2017-05-11T21:30:00.000Z",
"stop": "2017-05-11T22:00:00.000Z"
}
I've solved similar problems in the past using map() or alasql but the difference is in the datetime comparison. Can someone point me in the right direction?
My current solution is in Node so I am looking for assistance using Node/JavaScript.
Upvotes: 0
Views: 54
Reputation: 22237
A quick array.filter should do it:
var s = {
"times": [
{
"start": "2017-05-11T19:00:00.000Z",
"stop": "2017-05-11T19:30:00.000Z"
},
{
"start": "2017-05-11T19:30:00.000Z",
"stop": "2017-05-11T20:00:00.000Z"
},
{
"start": "2017-05-11T20:00:00.000Z",
"stop": "2017-05-11T20:30:00.000Z"
},
{
"start": "2017-05-11T20:30:00.000Z",
"stop": "2017-05-11T21:00:00.000Z"
},
{
"start": "2017-05-11T21:00:00.000Z",
"stop": "2017-05-11T21:30:00.000Z"
},
{
"start": "2017-05-11T21:30:00.000Z",
"stop": "2017-05-11T22:00:00.000Z"
}
],
"booked": [
{
"start": "2017-05-11T19:00:00.000Z",
"stop": "2017-05-11T20:30:00.000Z"
}
]
};
var avail = s.times.filter(function (el) {
for (var i = 0,b; b = s.booked[i]; i++) {
if (el.start < b.stop && el.stop > b.start) return false;
}
return true;
});
console.log(avail);
Upvotes: 2
Reputation: 7360
Something like that should work
function isFree(time) {
const tStart = time.start;
const tStop = time.stop;
// We order so if tStop < x.start we are sure no one of the following booking is overlapping
const occupiedSlot = t.booked.sort((a, b) => b.start - a.start);
for (let xx in occupiedSlot) {
let x = occupiedSlot[xx]
if (tStop < x.start) return true;
if (tStart > x.stop) continue;
if (tStart >= x.start && tStart < x.stop) return false;
if (tStart <= x.start && tStop > x.start) return false;
}
return true;
}
const t = {
"times": [
{
"start": "2017-05-11T19:00:00.000Z",
"stop": "2017-05-11T19:30:00.000Z"
},
{
"start": "2017-05-11T19:30:00.000Z",
"stop": "2017-05-11T20:00:00.000Z"
},
{
"start": "2017-05-11T20:00:00.000Z",
"stop": "2017-05-11T20:30:00.000Z"
},
{
"start": "2017-05-11T20:30:00.000Z",
"stop": "2017-05-11T21:00:00.000Z"
},
{
"start": "2017-05-11T21:00:00.000Z",
"stop": "2017-05-11T21:30:00.000Z"
},
{
"start": "2017-05-11T21:30:00.000Z",
"stop": "2017-05-11T22:00:00.000Z"
}
],
"booked": [
{
"start": "2017-05-11T19:00:00.000Z",
"stop": "2017-05-11T20:30:00.000Z"
}
]
}
const z = t.times.filter(isFree);
console.log(z)
Upvotes: 0
Reputation: 91525
Those are actually strings, not date objects, so you can compare them the way you would any string.
Javascript arrays have a .filter()
method which has a similar interface to the .map()
function. You give it a callback function and it spits out a new array where items from the original array are kept if the function returns true
, and discards them if false
.
var availableTimes = times.filter(function(time) {
return booked.filter(function(book) {
return book.start === time.start;
}).length > 0;
});
Upvotes: 0