简体   繁体   中英

How to calculate booking price depending on dates in an array in Javascript

I have two date vars: aankomst (arrival) and vertrek (departure). My goal is to calculate the total price of the stay from arrival to departure, which depends on low season, mid season and high season. I think I have a good theory of how to achieve this, and most of the script I made so far is working.

The final for loop is where I fail though. At that step I want to find the current date from the array in lowSeason, midSeason or peakSeason and add the costprice associated with that season to the total price. Here is the code, I added comments to show what I tried to do with each step and I also added plenty of alerts so I'm sure everything works until the for loop:

//fire function on load and  get the arrival date and departure date and make the array
window.onload = function getPrices() {
var aankomst = new Date();
var vertrek = new Date(aankomst.getTime() + (48 * 60 * 60 * 1000));
var maand = aankomst.getMonth();
var verblijfDagen = [];
var day = 1000*60*60*24;
var diff = (vertrek.getTime()- aankomst.getTime())/day;

//calculate all seperate days from arrival date to departure date and put them in an array   
for(var i=0;i<=diff; i++)
{
   var xx = aankomst.getTime()+day*i;
   var yy = new Date(xx);
   var zz = (yy.getDate()+"-"+(yy.getMonth()+1)+"-"+yy.getFullYear());
   var parts = zz.split('-');
   var zzDate = new Date(parts[2],parts[1]-1,parts[0]);
   //check if this date is in the correct Date structure
   alert(zzDate instanceof Date);
   verblijfDagen.push(zzDate)
}
//check if all the days are in the array
alert (verblijfDagen);

//declare the period of the different seasons and the daily cost rate during this season 
var peakSeason = {startDate: new Date(2017,10-1,01), endDate: new Date(2017,12-1,31), costRate: 500};
var midSeason = {startDate: new Date(2017,5-1,1), endDate: new Date(2017,9-1,30), costRate: 400};
var lowSeason = {startDate: new Date(2017,1-1,1), endDate: new Date(2017,4-1,30), costRate: 300};
var allSeasons = [peakSeason, midSeason, lowSeason]
//check if this date is in the correct Date structure
alert(lowSeason.startDate instanceof Date);
//check if the date is correct
alert (lowSeason.startDate);

//PROBLEM AREA check how many dates there are in the array and start the loop
var arrayLength = verblijfDagen.length;
for (var u = 0; u < arrayLength; u++) {
    //check if all dates of the array are looped
    alert(verblijfDagen[u]);
    //Iterate through allSeasons to find where the date belongs
    if (verblijfDagen[u] <= allSeasons.StartDate && allSeasons.verblijfDagen[u] >= endDate) {
    //Add costRate of this date to totalPrice
     var totalPrice = totalPrice + costRate;
    }
}
//return the total price
alert(totalPrice);
} 

Question:

  • What mistakes did I make with the loop and how can I fix it?
  • In the objects lowSeason, midSeason and peakSeason, I declared startDate and endDate I declared a year, so it currently only works for 2017, but the starting dates and end dates for each season should work for all years, how can I edit this? If needed, I'll ask this in a seperate question.

You forgot to iterate each of the seasons in your final loop.

But there is a nicer way to do all this: you don't need to store each day in an array. You can just iterate over the seasons and with simple arithmetic count how many days of the stay are overlapping with each season.

In this code the function receives three arguments: the seasons, the day of arrival, and day of departure. The function returns the price.

I have used as example a date of arrival that falls in one season, and a departure that falls in the next, so that the final price is 400+500=900.

 function getPrices(allSeasons, aankomst, vertrek) { const day = 1000*60*60*24; return allSeasons.reduce( (totalPrice, season) => { let daysInSeason = Math.floor( (Math.min(+season.endDate+day, vertrek) - Math.max(season.startDate, aankomst)) / day); return totalPrice + (daysInSeason > 0 && daysInSeason * season.costRate); }, 0); } const allSeasons = [ {startDate: new Date(2017, 1-1, 1), endDate: new Date(2017, 4-1,30), costRate: 300}, {startDate: new Date(2017, 5-1, 1), endDate: new Date(2017, 9-1,30), costRate: 400}, {startDate: new Date(2017,10-1, 1), endDate: new Date(2017,12-1,31), costRate: 500} ], aankomst = new Date(2017, 9-1,30), vertrek = new Date(aankomst.getTime() + (48 * 60 * 60 * 1000)), totalPrice = getPrices(allSeasons, aankomst, vertrek); console.log(totalPrice);

What mistakes did I make in the loop and how can I fix it?

You should declare the totalPrice variable before the loop and set it equal to zero so you can accumulate your price within the loop. Also the allSeasons variable is an array of objects but you were treating it as a simple object. So a way you can solve this is to do a second for loop within the first one to loop through the allSeasons array and compare dates. Lastly, the <= and >= were mixed up in the conditional statement. Here is a possible solution:

var totalPrice = 0; for (var u = 0; u < verblijfDagen.length; u++) { for(var j = 0; j < allSeasons.length; j++) { if (verblijfDagen[u] >= allSeasons[j].startDate && verblijfDagen[u] <= allSeasons[j].endDate) { //Add costRate of this date to totalPrice totalPrice = totalPrice + allSeasons[j].costRate; } } }

How to add a conditional in the code below in case there are no dates in this range, it assigns a fixed value for costRate?

function getPrices(allSeasons, aankomst, vertrek) {
    const day = 1000*60*60*24;
    return allSeasons.reduce( (totalPrice, season) => {
        let daysInSeason = Math.floor(
            (Math.min(+season.endDate+day, vertrek) 
             - Math.max(season.startDate, aankomst)) / day);
        return totalPrice + (daysInSeason > 0 && daysInSeason * season.costRate);
    }, 0);
} 

const allSeasons = [
        {startDate: new Date(2017, 1-1, 1), endDate: new Date(2017, 4-1,30), costRate: 300},
        {startDate: new Date(2017, 5-1, 1), endDate: new Date(2017, 9-1,30), costRate: 400},
        {startDate: new Date(2017,10-1, 1), endDate: new Date(2017,12-1,31), costRate: 500}
    ],
    aankomst = new Date(2017, 9-1,30),
    vertrek = new Date(aankomst.getTime() + (48 * 60 * 60 * 1000)),
    totalPrice = getPrices(allSeasons, aankomst, vertrek);

console.log(totalPrice);

What mistakes did I make with the loop and how can I fix it?

You shouldn't increment with the var keyword, and you are declaring the totalprice variable in the wrong scope. Moving it outside of the for loop lets you access it as needed. You should also try to avoid assigning variable names to one off values (like array length)

edit: you also seemed to have mixed up >= and <=

var totalPrice = 0;
for (var u = 0; u < verblijfDagen.length; u++) {       
    if (verblijfDagen[u] >= allSeasons.StartDate && allSeasons.verblijfDagen[u] <= endDate) {
     totalPrice += costRate;
    }
}
alert(totalPrice)

In the objects lowSeason, midSeason and peakSeason, I declared startDate and endDate I declared a year, so it currently only works for 2017, but the starting dates and end dates for each season should work for all years, how can I edit this?

For this I would take a look at moment.js . You can make a moment for your customer start and end dates and check their month values like so:

var aankomst = moment();
var vertrek = moment(aankomst).add(2, 'days')

var month = aankomst.month(); //note this method considers january as 0 and december as 11
switch(month){
    case month >= 9 && month <= 11:
        //peakseason stuff 
        break;
    case month >= 4 && month <= 8:
        //midseason stuff
        break;
    case month >= 0 && month <= 3:
        //lowseason stuff
        break;
}

In general when working with dates in JS I'd recommend everyone use moment, it is extremely helpful

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM