I might not be asking the right question here.
I'm retrieving bookings that have the first night and last night date and I'm trying to display on a calendar which dates are not available.
The date comes in as: firstNight: "2022-02-05" and currently, it needs to go out as Sat Feb 05 2022
In order to get a list of booked dates, I am doing the following:
const bookedDates = bedsData?.map(({ firstNight, lastNight }) => {
const newArrivalDate = new Date(firstNight + "T00:00")
const newDepartureDate = new Date(lastNight + "T24:00")
var getDaysArray = function (start, end) {
for (
var arr = [], dt = new Date(start);
dt <= end;
dt.setDate(dt.getDate() + 1)
) {
arr.push(new Date(dt).toDateString())
}
return arr
}
var daylist = getDaysArray(newArrivalDate, newDepartureDate)
daylist?.map((v) => v)
return daylist.join(", ")
})
This returns
0: undefined
1: "Sat Feb 05 2022, Sun Feb 06 2022, Mon Feb 07 2022, Tue Feb 08 2022, Wed Feb 09 2022, Thu Feb 10 2022, Fri Feb 11 2022, Sat Feb 12 2022"
2: undefined
3: "Sat Feb 12 2022, Sun Feb 13 2022, Mon Feb 14 2022, Tue Feb 15 2022, Wed Feb 16 2022, Thu Feb 17 2022, Fri Feb 18 2022, Sat Feb 19 2022"
4: "Sat Feb 19 2022, Sun Feb 20 2022, Mon Feb 21 2022, Tue Feb 22 2022, Wed Feb 23 2022, Thu Feb 24 2022, Fri Feb 25 2022, Sat Feb 26 2022"
5: undefined
6: undefined
7: "Sat Feb 26 2022, Sun Feb 27 2022, Mon Feb 28 2022, Tue Mar 01 2022, Wed Mar 02 2022, Thu Mar 03 2022, Fri Mar 04 2022, Sat Mar 05 2022"
8: "Sat Mar 05 2022, Sun Mar 06 2022, Mon Mar 07 2022, Tue Mar 08 2022, Wed Mar 09 2022, Thu Mar 10 2022, Fri Mar 11 2022, Sat Mar 12 2022"
9: undefined
10: undefined
11: "Fri Mar 25 2022, Sat Mar 26 2022, Sun Mar 27 2022, Mon Mar 28 2022, Tue Mar 29 2022"
To show which dates are booked I'm am using
if (bookedDates.join().includes(calDates)) {
style.textDecoration = "line-through"
style.color = "rgba(0, 0, 0, 0.25)"
}
The issue I'm facing is with dates that don't have a check out and check in on the same day. The "last day" and the "first day" of the next booking are still being included in the list of "bookedDates". However, they need to be "available" to check out or check in still.
I hope that makes sense... pretty lost with this one!
Thanks
I presume that in new Date(lastNight + "T24:00") that lastNight is in the format YYYY-MM-DD. Because there is no offset, the string will be parsed as local and the date will be set to 00:00 on the following day, i.e. 2022-02-06T24:00 will create a date with an identical time value to 2022-02-07T00:00.
It seems your souce data is booked nights, which you want to do use to disable dates that can't be selected as checkout days. So wherever there is an un–booked night, the following day can be selected as a checkout day even if it's booked.
So when making the array of dates to disable, check for gaps and remove the first booked date. You'll have to deal with this in the UI to indicate that the date can't be booked for checkin.
Another method would be to create the booked nights array, then wherever there's a gap delete the following night as gaps must always be two dates. The first is available for check in only, the last for checkout only.
E.g.
// Parse YYYY-MM-DD as local, not UTC
function parseLocal(s) {
let [y,m,d] = s.split(/\D/);
return new Date(y, m-1, d);
}
// Format as YYYY-MM-DD
function format(date = new Date()) {
return date.toLocaleDateString('en-CA'); // YYYY-MM-DD
}
// Add day to date (modifies date)
function addDay(date = new Date()) {
date.setDate(date.getDate() + 1);
return date;
}
let bookings = [
{id: 0,
firstNight: '2022-02-05',
lastNight: '2022-02-09'
},
{id: 1,
firstNight: '2022-02-10', // Contiguous booking, no gap
lastNight: '2022-02-15'
},
{id: 2,
firstNight: '2022-02-17', // Gap, 17th available for check out
lastNight: '2022-02-20'
},
{id: 3,
firstNight: '2022-02-21', // No gap, not avilable for checkout
lastNight: '2022-02-21'
},
{id: 4,
firstNight: '2022-02-22', // No gap, not avilable for checkout
lastNight: '2022-02-22'
},
{id: 4,
firstNight: '2022-02-24', // Gap, avilable for checkout
lastNight: '2022-02-24'
},
{id: 4,
firstNight: '2022-02-25', // No gap, not avilable for checkout
lastNight: '2022-02-25'
}
]
let bookedDates = bookings.map(
({firstNight, lastNight}) => [parseLocal(firstNight), parseLocal(lastNight)]
).reduce((dates, [firstNight, lastNight], i, mapDates) => {
// If lastNight of previous booking is not prevNight,
// don't add firstNight to array
let prevBookedNight = i? mapDates[i-1][1] : null;
if (i && format(addDay(prevBookedNight)) != format(firstNight)) {
addDay(firstNight);
}
while (firstNight <= lastNight) {
dates.push(format(firstNight));
firstNight.setDate(firstNight.getDate() + 1);
}
return dates;
},[]);
console.log('Not available for check in or out:\n' + bookedDates.join('\n'));
I am not sure I understud, but isn't it just a confusion with start and end limits of your for loop ? Did you try initializing with
if (firstNight!==lastNight) {
const newArrivalDate = new Date(firstNight + "T24:00")
const newDepartureDate = new Date(lastNight + "T00:00")
} else {
const newArrivalDate = new Date(firstNight + "T00:00")
const newDepartureDate = new Date(lastNight + "T00:00")
}