【问题标题】:How to calculate booking price depending on dates in an array in Javascript如何根据Javascript数组中的日期计算预订价格
【发布时间】:2017-11-20 20:26:27
【问题描述】:

我有两个日期变量:aankomst(到达)和 vertrek(出发)。我的目标是计算从抵达到离开的总住宿价格,这取决于淡季、中期和旺季。我认为我对如何实现这一点有一个很好的理论,并且到目前为止我制作的大部分脚本都可以正常工作。

最后的 for 循环是我失败的地方。在这一步,我想从 lowSeason、midSeason 或 peakSeason 的数组中找到当前日期,并将与该季节相关的成本价格添加到总价格中。这是代码,我添加了 cmets 以显示我尝试对每个步骤执行的操作,我还添加了大量警报,因此我确信在 for 循环之前一切正常:

//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);
} 

问题:

  • 我在循环中犯了哪些错误,如何解决?
  • 在对象 lowSeason、midSeason 和 peakSeason 中,我声明了 startDate 和 endDate 我声明了一年,所以它目前仅适用于 2017 年,但每个季节的开始日期和结束日期应该适用于所有年份,我该如何编辑这个?如果需要,我会在单独的问题中提出这个问题。

【问题讨论】:

  • 您应该修改或删除您的original question
  • 您好,请问怎么办?我很乐意进行相应的编辑。

标签: javascript arrays loops date for-loop


【解决方案1】:

您忘记在最终循环中迭代每个季节。

但是有一个更好的方法来做这一切:你不需要将每一天都存储在一个数组中。您可以迭代季节,并通过简单的算术计算每个季节的停留天数。

在这段代码中,函数接收三个参数:季节、到达日期和离开日期。该函数返回价格。

我以一个季节的到达日期和下一季节的出发日期为例,因此最终价格为 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);

【讨论】:

  • 感谢您的见解!我将另一个答案标记为解决方案,因为它更直接地解决了原始问题,但是剖析这真的很有趣,我肯定会尝试在我当前和未来的 javascript 编码中实现它!
【解决方案2】:

如果此范围内没有日期,如何在下面的代码中添加条件,它为 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);

【讨论】:

    【解决方案3】:

    我在循环中犯了哪些错误,我该如何解决?

    您应该在循环之前声明totalPrice 变量并将其设置为零,这样您就可以在循环内累积您的价格。 allSeasons 变量也是一个对象数组,但您将其视为一个简单对象。因此,您可以解决此问题的一种方法是在第一个 for 循环中执行第二个循环,以遍历 allSeasons 数组并比较日期。最后,&lt;=&gt;= 在条件语句中混淆了。这是一个可能的解决方案:

    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; } } }

    【讨论】:

    • 感谢您的解决方案和解释!完美运行。
    【解决方案4】:

    我在循环中犯了哪些错误,我该如何解决?

    您不应该使用 var 关键字递增,并且您在错误的范围内声明了 totalprice 变量。将其移出 for 循环可让您根据需要访问它。您还应该尽量避免将变量名称分配给一次性值(如数组长度)

    编辑:你似乎也混淆了&gt;=&lt;=

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

    在对象 lowSeason、midSeason 和 peakSeason 中,我声明了 startDate 和 endDate 我声明了一年,所以它目前仅适用于 2017 年,但每个季节的开始日期和结束日期应该适用于所有年份,我该如何编辑这个?

    为此,我想看看moment.js。您可以为客户的开始和结束日期留出时间,并检查他们的月份值,如下所示:

    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;
    }
    

    一般来说,在 JS 中处理日期时,我建议大家使用 moment,它非常有帮助

    【讨论】:

    • 感谢您的帮助!当我尝试代码时,alert(totalPrice) 返回了一个未定义的值,知道为什么吗?目前我不确定我是否能够使用时刻库​​,但我会尽快调查它。我希望你能检查这个问题,我自己也试试!再次感谢。
    • @KevinVerhoeven 那是因为我以这种方式初始化它,对我来说太糟糕了。你会想要var totalPrice = 0; 而不是var totalPrice
    • @KevinVerhoeven 未定义的值也部分是因为您的条件中混淆了&gt;=&lt;=。你想成为&gt;= 开始日期和&lt;= 结束日期
    • 所以 totalPrice 根本没有增加
    • 快到了!我也看到了 var totalPrice 的问题。现在警报返回 0。我想我可能还是在这里犯了错误? if (verblijfDagen[u] >= allSeasons.StartDate && allSeasons.verblijfDagen[u]
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多