Javascript 查找两个日期之间的天差(不包括周末)

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3464268/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 04:44:52  来源:igfitidea点击:

Find day difference between two dates (excluding weekend days)

javascriptjquery-ui

提问by cyberfly

Hi i am using jquery-ui datepicker to select date and date.jsto find difference between 2 dates.

嗨,我正在使用 jquery-ui datepicker来选择日期和date.js来查找 2 个日期之间的差异。

Right now the problem is I want to exclude weekend days from calculation (saturday and sunday). How should i do that?

现在的问题是我想从计算中排除周末(周六和周日)。我该怎么做?

For example the user select start date (13/8/2010) and end date (16/8/2010). Since 14/8/2010 and 15/8/2010 is in week days, instead of 4 days total, i want it to be only 2 days.

例如,用户选择开始日期 (13/8/2010) 和结束日期 (16/8/2010)。由于 14/8/2010 和 15/8/2010 是工作日,而不是总共 4 天,我希望它只有 2 天。

This is the code im using right now:

这是我现在使用的代码:

<script type="text/javascript">

    $("#startdate, #enddate").change(function() {       

    var d1 = $("#startdate").val();
    var d2 = $("#enddate").val();

            var minutes = 1000*60;
            var hours = minutes*60;
            var day = hours*24;

            var startdate1 = getDateFromFormat(d1, "d-m-y");
            var enddate1 = getDateFromFormat(d2, "d-m-y");

            var days = 1 + Math.round((enddate1 - startdate1)/day);             

    if(days>0)
    { $("#noofdays").val(days);}
    else
    { $("#noofdays").val(0);}


    });

    </script>

回答by Garis M Suero

Maybe someone else can help you converting this function into JQuery's framework...

也许其他人可以帮助您将此功能转换为 JQuery 的框架...

I found this function here.

我在这里找到了这个功能。

function calcBusinessDays(dDate1, dDate2) { // input given as Date objects
  var iWeeks, iDateDiff, iAdjust = 0;
  if (dDate2 < dDate1) return -1; // error code if dates transposed
  var iWeekday1 = dDate1.getDay(); // day of week
  var iWeekday2 = dDate2.getDay();
  iWeekday1 = (iWeekday1 == 0) ? 7 : iWeekday1; // change Sunday from 0 to 7
  iWeekday2 = (iWeekday2 == 0) ? 7 : iWeekday2;
  if ((iWeekday1 > 5) && (iWeekday2 > 5)) iAdjust = 1; // adjustment if both days on weekend
  iWeekday1 = (iWeekday1 > 5) ? 5 : iWeekday1; // only count weekdays
  iWeekday2 = (iWeekday2 > 5) ? 5 : iWeekday2;

  // calculate differnece in weeks (1000mS * 60sec * 60min * 24hrs * 7 days = 604800000)
  iWeeks = Math.floor((dDate2.getTime() - dDate1.getTime()) / 604800000)

  if (iWeekday1 < iWeekday2) { //Equal to makes it reduce 5 days
    iDateDiff = (iWeeks * 5) + (iWeekday2 - iWeekday1)
  } else {
    iDateDiff = ((iWeeks + 1) * 5) - (iWeekday1 - iWeekday2)
  }

  iDateDiff -= iAdjust // take into account both days on weekend

  return (iDateDiff + 1); // add 1 because dates are inclusive
}

var date1 = new Date("August 11, 2010 11:13:00");
var date2 = new Date("August 16, 2010 11:13:00");
alert(calcBusinessDays(date1, date2));

## EDITED ##

##已编辑##

If you want to use it with your that format just:

如果您想将它与您的格式一起使用:

Your code will look like:

您的代码将如下所示:

function calcBusinessDays(dDate1, dDate2) { // input given as Date objects
  var iWeeks, iDateDiff, iAdjust = 0;
  if (dDate2 < dDate1) return -1; // error code if dates transposed
  var iWeekday1 = dDate1.getDay(); // day of week
  var iWeekday2 = dDate2.getDay();
  iWeekday1 = (iWeekday1 == 0) ? 7 : iWeekday1; // change Sunday from 0 to 7
  iWeekday2 = (iWeekday2 == 0) ? 7 : iWeekday2;
  if ((iWeekday1 > 5) && (iWeekday2 > 5)) iAdjust = 1; // adjustment if both days on weekend
  iWeekday1 = (iWeekday1 > 5) ? 5 : iWeekday1; // only count weekdays
  iWeekday2 = (iWeekday2 > 5) ? 5 : iWeekday2;

  // calculate differnece in weeks (1000mS * 60sec * 60min * 24hrs * 7 days = 604800000)
  iWeeks = Math.floor((dDate2.getTime() - dDate1.getTime()) / 604800000)

  if (iWeekday1 < iWeekday2) { //Equal to makes it reduce 5 days
    iDateDiff = (iWeeks * 5) + (iWeekday2 - iWeekday1)
  } else {
    iDateDiff = ((iWeeks + 1) * 5) - (iWeekday1 - iWeekday2)
  }

  iDateDiff -= iAdjust // take into account both days on weekend

  return (iDateDiff + 1); // add 1 because dates are inclusive
}


$("#startdate, #enddate").change(function() {

  var d1 = $("#startdate").val();
  var d2 = $("#enddate").val();

  var minutes = 1000 * 60;
  var hours = minutes * 60;
  var day = hours * 24;

  var startdate1 = new Date(d1);
  var enddate1 = new Date(d2);


  var newstartdate = new Date();
  newstartdate.setFullYear(startdate1.getYear(), startdate1.getMonth(), startdate1.getDay());
  var newenddate = new Date();
  newenddate.setFullYear(enddate1.getYear(), enddate1.getMonth(), enddate1.getDay());
  var days = calcBusinessDays(newstartdate, newenddate);
  if (days > 0) {
    $("#noofdays").val(days);
  } else {
    $("#noofdays").val(0);
  }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<label>Start Date
 <input type="date" id="startdate" value="2019-03-03"/>
</label>

<label>End Date
 <input type="date" id="enddate" value="2019-03-06"/>
</label>

<label>N. of days
 <output id="noofdays"/>
</label>

回答by cyberfly

To do this, you should NOT search all days between these dates !

为此,您不应搜索这些日期之间的所有日子!

It's not complicated, look some evident assumptions:

并不复杂,看一些明显的假设:

  1. All full-week has 7-days.

  2. Which 2 are weekend-days.

  3. And which 5 are business-day.

  1. 所有整周都有 7 天。

  2. 其中 2 天是周末。

  3. 其中 5 个是工作日。

Evident conclusions:

明显的结论:

  1. Look all days is loss of time.

  2. Check what day is weekend to all week is loss of time.

  1. 看所有的日子都是在浪费时间。

  2. 检查哪一天是周末到整个星期都在浪费时间。



Without tedious explanation.. let me show the code:

没有繁琐的解释..让我展示代码:

function getBusinessDateCount (startDate, endDate) {
    var elapsed, daysBeforeFirstSaturday, daysAfterLastSunday;
    var ifThen = function (a, b, c) {
        return a == b ? c : a;
    };

    elapsed = endDate - startDate;
    elapsed /= 86400000;

    daysBeforeFirstSunday = (7 - startDate.getDay()) % 7;
    daysAfterLastSunday = endDate.getDay();

    elapsed -= (daysBeforeFirstSunday + daysAfterLastSunday);
    elapsed = (elapsed / 7) * 5;
    elapsed += ifThen(daysBeforeFirstSunday - 1, -1, 0) + ifThen(daysAfterLastSunday, 6, 5);

    return Math.ceil(elapsed);
}

function calc() {
  let start = document.querySelector('#startDate').value,
      end = document.querySelector('#endDate').value,
      result = getBusinessDateCount(new Date(start), new Date(end));
  document.querySelector('#result').value = result;
}
Start date: <input type="date" id="startDate" value="2020-01-04"><br>
End date: <input type="date" id="endDate" value="2020-01-06"><br>
<input type="button" onclick="calc()" value="Get business days"><br>
Business days: <input id="result" readonly>

You can test it yourself with any dates.

您可以使用任何日期自行测试。

I just want to notice that this code ONLY consumed 0.43 secbetween dates from 2000 to 2015... It is much more fast than some other codes.

我只是想注意到这段代码在 2000 年到 2015 年的日期之间只消耗了 0.43 秒......它比其他一些代码快得多。

Hope it helps...

希望能帮助到你...

Nice coding !!

不错的编码!!

回答by sberry

This is how I would do it

这就是我要做的

function getDays(d1, d2) {
    var one_day=1000*60*60*24;
    var d1_days = parseInt(d1.getTime()/one_day) - 1;
    var d2_days = parseInt(d2.getTime()/one_day);
    var days = (d2_days - d1_days);
    var weeks = (d2_days - d1_days) / 7;
    var day1 = d1.getDay();
    var day2 = d2.getDay();
    if (day1 == 0) {
        days--;
    } else if (day1 == 6) {
        days-=2;
    }
    if (day2 == 0) {
       days-=2;
    } else if (day2 == 6) {
       days--;
    }
    days -= parseInt(weeks) * 2;
    alert(days);
}

getDays(new Date("June 8, 2004"),new Date("February 6, 2010"));

EDIT
To clarify my comment to @keenebec...
That solution will work for small date differences quite nicely and is easy to understand. But take something as "short" as a 6 year span and you can see a remarkable difference in speed.

编辑
为了澄清我对@keenebec 的评论......
该解决方案将很好地适用于小日期差异,并且易于理解。但是将一些“短”的东西作为 6 年的跨度,您会看到速度的显着差异。

http://jsfiddle.net/aSvxv/

http://jsfiddle.net/aSvxv/

I included all 3 answers and the original answer is indeed the fastest, but not by much and the trade off for a few microseconds of execution is somewhat trivial to me in favor of readability.

我包含了所有 3 个答案,原始答案确实是最快的,但速度并不快,而且为了提高可读性,几微秒的执行权衡对我来说有些微不足道。

回答by Vadim Gremyachev

Date.prototype.addDays = function(days) {
    var date = new Date(this.valueOf())
    date.setDate(date.getDate() + days);
    return date;
}

function getBusinessDatesCount(startDate, endDate) {
    var count = 0;
    var curDate = startDate;
    while (curDate <= endDate) {
        var dayOfWeek = curDate.getDay();
        var isWeekend = (dayOfWeek == 6) || (dayOfWeek == 0); 
        if(!isWeekend)
           count++;
        curDate = curDate.addDays(1);
    }
    return count;
}



//Usage
var startDate = new Date('7/16/2015');
var endDate = new Date('7/20/2015');
var numOfDays = getBusinessDatesCount(startDate,endDate);
jQuery('div#result').text(numOfDays);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="result"/>

回答by kennebec

That looks like too much work to me. I'd rather let the computer do the heavy lifting- //

对我来说,这看起来工作量太大了。我宁愿让电脑做繁重的工作- //

Date.bizdays= function(d1, d2){
    var bd= 0, dd, incr=d1.getDate();
    while(d1<d2){
        d1.setDate(++incr);
        dd= d1.getDay();
        if(dd%6)++bd;
    }
    return bd;
}

//test

var day1= new Date(2010, 7, 11), day2= new Date(2010, 7, 31);

alert(Date.bizdays(day1, day2))

回答by Thisara Subath

To understand way.,

理解方式。,



  1. Actual days = 14
  2. weeks for Actual days = 14/7=2
  3. Weekends per week=2
  4. Total weekends=2*weeks for days
  1. 实际天数 = 14
  2. 实际天数的周数 = 14/7=2
  3. 每周周末=2
  4. 周末总数=2*周数


So apply this ,

所以应用这个,

 $('#EndDate').on('change', function () {
            var start = $('#StartDate').datepicker('getDate');
            var end = $('#EndDate').datepicker('getDate');
            if (start < end) {
                var days = (end - start) / 1000 / 60 / 60 / 24;

                var Weeks=Math.round(days)/7;

                var totalWeekends=Math.round(Weeks)*2;

                var puredays=Math.round(days)-totalWeekends;

                $('#days').text(Math.round(puredays) + "Working Days");


            }
            else {
alert("");
}

Thank you !

谢谢 !

回答by Andy

There seems to be few issues with the response that has been marked as solution.

被标记为解决方案的响应似乎没有什么问题。

  • The statement setFullYear() is returning incorrect value if I choose start date as 06/11/2015. So instead, the startDate1 and endDate1 can be directly passed to the function.

  • If the start date is Saturday or Sunday, still the code is counting it(iWeekday1) as 5 days

  • If the end date is Saturday or Sunday, still the code is counting it(iWeekday2) as 5 days. But these 5 days already get counted in the iweeks calculation.
    So instead of
    iWeekday1 = (iWeekday1 > 5) ? 5 : iWeekday1; // only count weekdays
    iWeekday2 = (iWeekday2 > 5) ? 5 : iWeekday2;

    it should be
    iWeekday1 = (iWeekday1 > 5) ? 0: iWeekday1; // only count weekdays
    iWeekday2 = (iWeekday2 > 5) ? 0: iWeekday2;

  • The last IF condition should be executed when start and end date day is same like both are on same day, the date could be different
    if (iWeekday1 <=iWeekday2)

  • The condition that adjusts if both days are weekends can be removed
    iDateDiff -= iAdjust

  • Lastly, the +1 should be done only if start and end date falls on weekdays. Currently, it is adding in both the cases.
    return (iDateDiff + 1);//Add condition to apply only if both days are weekdays

  • 如果我选择开始日期为 06/11/2015,语句 setFullYear() 将返回不正确的值。因此,可以将 startDate1 和 endDate1 直接传递给函数。

  • 如果开始日期是星期六或星期日,代码仍然将其(iWeekday1)计为 5 天

  • 如果结束日期是星期六或星期日,代码仍然将其(iWeekday2)计为 5 天。但是这 5 天已经被计入 iweeks 计算中。
    所以不是
    iWeekday1 = (iWeekday1 > 5) ?5 : iWeekday1; // 只计算工作日
    iWeekday2 = (iWeekday2 > 5) ? 5 : iWeekday2;

    应该是
    iWeekday1 = (iWeekday1 > 5) ?0: iWeekday1; // 只计算工作日
    iWeekday2 = (iWeekday2 > 5) ? 0: iWeekday2;

  • 当开始日期和结束日期相同时应执行最后一个 IF 条件,例如两者都在同一天,
    如果 (iWeekday1 < =iWeekday2)日期可能不同

  • 如果两天都是周末调整的条件可以去掉
    iDateDiff -= iAdjust

  • 最后,仅当开始和结束日期在工作日时才应执行 +1。目前,它正在添加这两种情况。
    返回 (iDateDiff + 1); //添加仅当这两天都是工作日时才应用的条件

--can't comment on that answer as I do not have that reputation :)

--不能评论那个答案,因为我没有那个名声:)

回答by PPM1988

I have used Angular framework and Moment.js library to implement the solution. My solution covers all the cases.

我使用了 Angular 框架和 Moment.js 库来实现该解决方案。我的解决方案涵盖了所有情况。

this.daysInBetween = this.endMoment.diff(this.startMoment, 'days') + 1;
this.weeksInBetween = this.endMoment.diff(this.startMoment, 'weeks');
this.weekDays = this.daysInBetween - (this.weeksInBetween * 2);

if ( (this.startMoment.day() === 0 && this.endMoment.day() === 6) ||
 (this.startMoment.day() > this.endMoment.day()) ) {
  // IF ONE WEEKEND WAS MISSED
  this.weekDays-=2;
} else if ( this.startMoment.day() <= this.endMoment.day() &&
( this.startMoment.day() === 0 || this.startMoment.day() === 6 ||
  this.endMoment.day() === 0 || this.endMoment.day() === 6) ) {
  // IF EITHER OF DAYS WAS A WEEKEND
  this.weekDays--;
}

Live Demo: Calculate number of weekdays

现场演示: 计算工作日数

I am currently working on a blog to write about my approach to this specific problem. I will post the link to the blog on the comment.

我目前正在写一个博客来写我解决这个特定问题的方法。我将在评论中发布指向该博客的链接。

回答by sudheer nunna

function addDays(date, days) {
    var result = new Date(date);
    result.setDate(result.getDate() + days);
    return result;
}
 var currentDate;
                            selectFlixbleDates = [];
                            var monToSatDateFilter=[];
                            currentDate=new Date(date);
                            while(currentDate){
                                console.log("currentDate"+currentDate);
                                if(new Date(currentDate).getDay()!=0){
                                    selectFlixbleDates.push(currentDate)
                                }
                                if(selectFlixbleDates.length==$scope.numberOfDatePick)
                                {

                                    break;
                                }
                                currentDate=addDays(currentDate,1);

                            }
                            for (var i = 0; i < selectFlixbleDates.length; i++) {

                                //  console.log(between[i]);
                                monToSatDateFilter.push((selectFlixbleDates[i].getMonth() + 1) + '/' + selectFlixbleDates[i].getDate() + '/' + selectFlixbleDates[i].getFullYear());

                            }
                            var endDate=monToSatDateFilter.slice(-1).pop();
                            var space =monToSatDateFilter.join(', ');
                            var sdfs= document.getElementById("maxPicks").value =space;
                            $scope.$apply(function() {
                                $scope.orderEndDate=monToSatDateFilter.slice(-1).pop()
                                $scope.orderStartDate=monToSatDateFilter[0];
                            });
                            document.getElementById("startDateEndDate").innerHTML =$scope.orderStartDate+ ' TO ' +$scope.orderEndDate
                        }  

回答by Tim Gerhard

Important:Most answers here don't actually work if the start date (or sometimes the end date) is a saturday or sunday. I took the accepted response and modified it so that this issue is resolved now:

重要提示:如果开始日期(或有时是结束日期)是星期六或星期日,则此处的大多数答案实际上不起作用。我接受了接受的回复并对其进行了修改,以便现在解决此问题:

    var dateDiff;
    if (dateTo < dateFrom) return -1; // error code if dates transposed
    var dateFromDayOrig = dateFrom.getDay(); // day of week
    var dateToDayOrig = dateTo.getDay();
    var dateFromDay = (dateFromDayOrig == 0) ? 7 : dateFromDayOrig; // change Sunday from 0 to 7
    var dateToDay = (dateToDayOrig == 0) ? 7 : dateToDayOrig;
    dateFromDay = (dateFromDay > 5) ? 5 : dateFromDay; // only count weekdays
    dateToDay = (dateToDay > 5) ? 5 : dateToDay;

    // calculate differnece in weeks (1000mS * 60sec * 60min * 24hrs * 7 days = 604800000)
    var weekDifference = Math.floor((dateTo.getTime() - dateFrom.getTime()) / 604800000);

    if (dateFromDay <= dateToDay) {
        dateDiff = (weekDifference * 5) + (dateToDay - dateFromDay);
    } else {
        dateDiff = ((weekDifference + 1) * 5) - (dateFromDay - dateToDay);
    }

    // fix: remove one day if it's saturday or sunday
    if (dateFromDayOrig >= 6 || dateFromDayOrig == 0) {
    dateDiff--;
    }

    return (dateDiff + 1); // add 1 because dates are inclusive