【问题标题】:Find day difference between two dates (excluding weekend days)查找两个日期之间的天差(不包括周末)
【发布时间】:2010-08-12 02:06:37
【问题描述】:

您好,我正在使用 jquery-ui datepicker 来选择日期,并使用 date.js 来查找两个日期之间的差异。

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

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

这是我现在使用的代码:

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

【问题讨论】:

    标签: javascript jquery-ui


    【解决方案1】:

    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"/>

    【讨论】:

      【解决方案2】:

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

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

      1. 所有整周都有 7 天。

      2. 哪 2 天是周末。

      3. 其中 5 个是工作日。

      确凿的结论:

      1. 整天看就是浪费时间。

      2. 检查周末到哪一天是浪费时间。


      不用繁琐的解释..让我展示代码:

      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>

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

      我只是想注意this code ONLY consumed 0.43 sec 在 2000 年到 2015 年之间的日期...它比其他一些代码快得多。

      希望对你有帮助……

      编码不错!!

      【讨论】:

      • 周末开始时不正确计数Reproduction of the bug。当它应该是 5 时,它计数 3 天。
      • @Alvaro。非常感谢您的回复..我已经更新了功能..现在检查它是否适合您
      • 非常感谢,现在好像可以正常使用了!
      【解决方案3】:

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

          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
      

      【讨论】:

      • 我使用这段代码已经有一段时间了,它大多非常可靠,但我现在意识到有一个缺陷,如果日期之间有 7 天的差异,它会给出一个周差为 0 ` dateTo:2021 年 5 月 11 日星期二 23:59:59 GMT+0100(英国夏令时间)``dateFrom:2021 年 5 月 4 日星期二 00:00:00 GMT+0100(英国夏令时)``weekDifference:0days`
      • 例如:开始日期:1620319036957 结束日期:1620860400000 周差返回:0
      【解决方案4】:

      也许别人可以帮你把这个函数转换成JQuery的框架……

      我找到了这个函数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));

      ##已编辑##

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

      您的代码将如下所示:

      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>

      【讨论】:

      • 谢谢我让它工作,虽然代码有点不同。无论如何,非常感谢您的帮助。我被这个问题困扰了 2 天,直到我找到了 stackoverflow 和你的大力帮助。
      • +1 用于发布对原始代码的引用!其实我当初看帖子的时候并没有看到。 +1 也是因为代码比我的解决方案快,但不是很多:)
      • @GarisMSuero calcBusinessDays 它不适用于任何两个日期,请尝试使用“20140328”和“20140404”;结果为0,这是错误的;发生这种情况是因为 UTC 偏移;请查看这篇帖子,Michael Liu 的回答:stackoverflow.com/questions/542938/…
      • 这个脚本不能正常工作。它显示 1 天,从星期日开始到星期五结束。 Reproduction of the bug here
      • 它给出了错误的结果。如果您选择开始日期“06-11-2015”和结束日期“06-18-2015”..它给出的结果为 1。它应该是5
      【解决方案5】:

      标记为解决方案的响应似乎很少有问题。

      • 如果我选择开始日期为 2015 年 6 月 11 日,语句 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 条件应该在开始和结束日期相同时执行,就像两者在同一天一样,日期可能不同
        if (iWeekday1 = iWeekday2)

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

      • 最后,只有当开始和结束日期在工作日时,才应该进行 +1。目前,这两种情况都在增加。
        return (iDateDiff + 1);//添加条件,仅当这两天都是工作日时才适用

      --无法评论该答案,因为我没有那种声誉:)

      【讨论】:

        【解决方案6】:

        我会这样做

        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"));
        

        编辑
        澄清我对@keenebec 的评论...
        该解决方案适用于较小的日期差异,并且易于理解。但是,以 6 年为“短”的时间跨度,您会看到速度上的显着差异。

        http://jsfiddle.net/aSvxv/

        我包含了所有 3 个答案,原来的答案确实是最快的,但不是很多,而且执行几微秒的权衡对我来说有点微不足道,有利于可读性。

        【讨论】:

        • 这应该是公认的答案。 Garis 的一个错误在周末开始和结束 (reproduction of Garis bug)
        • 这是一篇旧帖子,但想知道是否有任何方法可以修改它以将时间也考虑在内并提供天数差异作为分数 - 例如:2 个时间戳之间的差异是 2.35 天后不包括周末
        • 星期四开始并在星期一结束时失败。 Reproduction of the bug。有 3 个工作日,其报告时间为 5 个。
        • 修复第2天小于第1天的问题:if (day2 &lt; day1) weeks++;
        【解决方案7】:

        理解方式,


        1. 实际天数 = 14
        2. 实际天数的周数 = 14/7=2
        3. 每周周末=2
        4. 总周末=2*周数

        所以应用这个,

         $('#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("");
        }
        

        谢谢!

        【讨论】:

        • 如果我想得到像 { week1: 3 个工作日, week2: 5 个工作日 ....}
        • 那么你需要设置计算来找出像:Total days / 7 = week rest is days .
        【解决方案8】:

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

        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))
        

        【讨论】:

        • 这绝对是一个非常可行的解决方案。但是,这确实意味着“相当”大量的迭代,这可能会或可能不会在客户端机器上产生很大的开销,但仍然可以很好地回答。
        • 通过获得 floor((d2-d1)/7) 来丢失大部分工作怎么样?这为您提供了周数,全部包含 5 个工作日。然后使用前滚来完成它。
        【解决方案9】:

        我可以使用此代码。请注意,该函数来自 date.js 和 businessday js(感谢 Garis Suero)。开始日期 11-08-2010 结束日期 16-08-2010 将导致 4 天的假期。

        <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 = calcBusinessDays(new Date(startdate1),new Date(enddate1));             
        
            if(days>0)
            { $("#noofdays").val(days);}
            else
            { $("#noofdays").val(0);}
        
        
            });
        
            </script>
        

        【讨论】:

          【解决方案10】:

          我做了什么

          function calcbusinessdays()
          {
              for(var c=0,e=0,d=new Date($("#startdate").val()),a=(new Date($("#enddate").val())-d)/864E5;0<=a;a--)
              {
                  var b=new Date(d);
                  b.setDate(b.getDate()+a);
                  1==Math.ceil(b.getDay()%6/6)?c++:e++
              }
              $("#noofdays").html(c)
          };
          

          c 是工作日,e 是周末

          【讨论】:

            【解决方案11】:
            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
                                    }  
            

            【讨论】:

              【解决方案12】:

              我已经使用 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--;
              }
              

              现场演示: Calculate number of weekdays

              我目前正在写一个博客来介绍我的处理方法 具体问题。我会在评论上贴出博客的链接。

              【讨论】:

                【解决方案13】:

                重要提示:如果开始日期(或有时结束日期)是星期六或星期日,这里的大多数答案实际上都不起作用。 例如:如果您的开始和结束日期是

                • 周六至周日,反之亦然
                • 周六到周六
                • 周日至周日

                所以,这里是接受答案的修改后的答案

                function calculateBusinessDays(dDate1, dDate2) {
                
                var iWeeks, iDateDiff, iAdjust = 0;
                if (dDate2 < dDate1) {
                    return -1;
                }
                
                var iWeekday1 = dDate1.getDay();
                var iWeekday2 = dDate2.getDay();
                
                iWeekday1 = (iWeekday1 === 0) ? 7 : iWeekday1;
                iWeekday2 = (iWeekday2 === 0) ? 7 : iWeekday2;
                
                if (iWeekday1 > 5 && iWeekday2 <= 6) {
                    iWeekday1 = 0;
                    iAdjust = 1;
                }
                iWeekday2 = (iWeekday1 === 0 && iWeekday2 === 6) ? 0 : iWeekday2;
                
                if ((iWeekday1 > 5) && (iWeekday2 > 5)) iAdjust = 1;
                
                iWeekday1 = (iWeekday1 > 5) ? 5 : iWeekday1;
                iWeekday2 = (iWeekday2 > 5) ? 5 : iWeekday2;
                iWeeks = Math.floor((dDate2.getTime() - dDate1.getTime()) / 604800000);
                
                if (iWeeks===0 && iWeekday1===0 && iWeekday2===0 
                    && (dDate2.getTime() !== dDate1.getTime()) ) {
                    iWeeks = 1;
                }
                
                if (iWeekday1 <= iWeekday2) {
                    iDateDiff = (iWeeks * 5) + (iWeekday2 - iWeekday1)
                } else {
                    iDateDiff = ((iWeeks + 1) * 5) - (iWeekday1 - iWeekday2)
                }
                iDateDiff -= iAdjust
                return (iDateDiff + 1);
                

                }

                【讨论】:

                  猜你喜欢
                  • 1970-01-01
                  • 2019-04-15
                  • 1970-01-01
                  • 2011-04-06
                  • 1970-01-01
                  • 2019-12-10
                  • 1970-01-01
                  • 2019-12-03
                  相关资源
                  最近更新 更多