在javascript日期计算中排除周末

IT技术 javascript datetime
2021-01-21 03:55:29

我有两组有效的代码。需要帮助将它们合二为一。

这段代码让我知道两个日期之间的差异。完美运行:

function test(){
var date1 = new Date(txtbox_1.value);    
var date2 = new Date(txtbox_2.value);

var diff = (date2 - date1)/1000;
var diff = Math.abs(Math.floor(diff));

var days = Math.floor(diff/(24*60*60));
var leftSec = diff - days * 24*60*60;

var hrs = Math.floor(leftSec/(60*60));
var leftSec = leftSec - hrs * 60*60;

var min = Math.floor(leftSec/(60));
var leftSec = leftSec - min * 60;

txtbox_3.value = days + "." + hrs; }

上述代码的来源

@cyberfly 下面的代码似乎有排除 sat 和 sun 的答案,这正是我需要的。来源但是,它在 jquery 中,上面的代码在 JS 中。因此,需要帮助结合,因为我缺乏知识:(

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

编辑 尝试结合代码。这是我的样本。获取对象预期错误

function test(){
var date1 = new Date(startdate.value);    
var date2 = new Date(enddate.value);
var diff = (date2 - date1)/1000;
var diff = Math.abs(Math.floor(diff)); 
var days = Math.floor(diff/(24*60*60));
var leftSec = diff - days * 24*60*60;
var hrs = Math.floor(leftSec/(60*60));
var leftSec = leftSec - hrs * 60*60;
var min = Math.floor(leftSec/(60));
var leftSec = leftSec - min * 60;

var startdate1 = getDateFromFormat(startdate, "dd/mm/yyyy hh:mm");
var enddate1 = getDateFromFormat(enddate, "dd/mm/yyyy hh:mm");
days = calcBusinessDays(new Date(startdate1),new Date(enddate1));           
noofdays.value = days + "." + hrs; }

start: <input type="text" id="startdate" name="startdate" value="02/03/2015 00:00">
end: <input type="text" id="enddate" name="enddate" value="02/03/2015 00:01">
<input type="text" id="noofdays" name="noofdays" value="">

6个回答

在确定两个日期之间的天数时,需要做出很多关于什么是一天的决定。例如,2月1日至2月2日期间一般为1天,因此2月1日至2月1日为0天。

当增加仅计算工作日的复杂性时,事情会变得更加困难。例如,从 2015 年 2 月 2 日星期一到 2 月 6 日星期五是 4 天(星期一到星期二是 1,星期一到星期三是 2,等等),但是表达“星期一到星期五”通常被视为 5 个工作日,持续时间为星期一 2 2 月至 2 月 7 日周六也应为 4 个工作日,但周日至周六应为 5 个工作日。

所以这是我的算法:

  1. 获取两个日期之间的总天数
  2. 除以 7 得到整周数
  3. 将周数乘以 2 得到周末天数
  4. 从总数中减去周末天数得到工作日
  5. 如果总天数不是偶数周数,则将周数 * 7 添加到开始日期以获得临时日期
  6. 虽然临时日期小于结束日期:
  • 如果临时日期不是星期六或星期日,请添加一个工作日
  • 添加一个到临时日期
  1. 而已。

最后的步进部分可能会被其他一些算法取代,但它永远不会循环超过 6 天,因此它是解决不均匀周问题的简单且合理有效的解决方案。

以上的一些后果:

  1. 周一至周五为 4 个工作日
  2. 不同周中同一天的任何一天都是偶数周,因此是 5 的偶数倍数,例如 2 月 2 日星期一至 2 月 9 日星期一和 2 月 1 日星期日至 2 月 8 日星期日是 5 个工作日
  3. 2 月 6 日星期五至 2 月 7 日星期日为零工作日
  4. 2月6日星期五至2月9日星期一是一个工作日
  5. 2 月 8 日星期日至:2 月 15 日星期日、2 月 14 日星期六和 2 月 13 日星期五均为 5 个工作日

这是代码:

// Expects start date to be before end date
// start and end are Date objects
function dateDifference(start, end) {

  // Copy date objects so don't modify originals
  var s = new Date(+start);
  var e = new Date(+end);
  
  // Set time to midday to avoid dalight saving and browser quirks
  s.setHours(12,0,0,0);
  e.setHours(12,0,0,0);
  
  // Get the difference in whole days
  var totalDays = Math.round((e - s) / 8.64e7);
  
  // Get the difference in whole weeks
  var wholeWeeks = totalDays / 7 | 0;
  
  // Estimate business days as number of whole weeks * 5
  var days = wholeWeeks * 5;

  // If not even number of weeks, calc remaining weekend days
  if (totalDays % 7) {
    s.setDate(s.getDate() + wholeWeeks * 7);
    
    while (s < e) {
      s.setDate(s.getDate() + 1);

      // If day isn't a Sunday or Saturday, add to business days
      if (s.getDay() != 0 && s.getDay() != 6) {
        ++days;
      }
    }
  }
  return days;
}

我不知道它与 jfriend00 的答案或您引用的代码相比如何,如果您希望该时间段包含在内,如果开始或结束日期是工作日,只需添加一个。

2021-03-24 03:55:29
@RobG 这将返回天数,如果我们也想显示所有结果日期怎么办?能不能稍微修改一下。谢谢
2021-03-24 03:55:29
非常感谢罗布的详细解释。我无法告诉你我有多感谢你的时间和努力。您的解决方案效果很好!!:)
2021-03-28 03:55:29
@Mogambo——什么是“结果日期”?如果你的意思是周末日期被排除在外,那是一个不同的问题,所以不,我不会修改答案。
2021-04-12 03:55:29

这是一个计算两个日期对象之间的工作日数的简单函数。按照设计,它不计算开始日,但计算结束日,因此如果您在一周的周二和下周的周二为其指定日期,它将返回 5 个工作日。这不考虑假期,但在夏令时变化中可以正常工作。

function calcBusinessDays(start, end) {
    // This makes no effort to account for holidays
    // Counts end day, does not count start day

    // make copies we can normalize without changing passed in objects    
    var start = new Date(start);
    var end = new Date(end);

    // initial total
    var totalBusinessDays = 0;

    // normalize both start and end to beginning of the day
    start.setHours(0,0,0,0);
    end.setHours(0,0,0,0);

    var current = new Date(start);
    current.setDate(current.getDate() + 1);
    var day;
    // loop through each day, checking
    while (current <= end) {
        day = current.getDay();
        if (day >= 1 && day <= 5) {
            ++totalBusinessDays;
        }
        current.setDate(current.getDate() + 1);
    }
    return totalBusinessDays;
}

并且,用于演示的 jQuery + jQueryUI 代码:

// make both input fields into date pickers
$("#startDate, #endDate").datepicker();

// process click to calculate the difference between the two days
$("#calc").click(function(e) {
    var diff = calcBusinessDays(
        $("#startDate").datepicker("getDate"), 
        $("#endDate").datepicker("getDate")
    );
    $("#diff").html(diff);
});

而且,这是一个使用 jQueryUI 中的日期选择器构建的简单演示:http : //jsfiddle.net/jfriend00/z1txs10d/

回复:“ ……但在夏令时变化中确实可以正常工作”。Safari 中存在一个错误,它在转换日期提前 4 小时应用夏令时,因此最后一天的午夜变为 23:00(反之亦然)。不过可能不会影响你的算法。我将时间设置为中午和圆形,以便至少避免一整天。
2021-03-18 03:55:29
这在 2021 年 1 月不起作用。显示 20 天
2021-03-31 03:55:29
@jfriend00 你能看看这个吗?stackoverflow.com/questions/47435105/...
2021-04-05 03:55:29
@jfriend00 非常感谢你的伙伴,我也尝试了你的解决方案,效果很好!!再次感谢您的时间和帮助。
2021-04-08 03:55:29

@RobG 提供了一种出色的算法来将工作日与周末分开。我认为唯一的问题是如果开始日期是周末、周六或周日,那么工作日/周末的数量会减少一个。

更正后的代码如下。

function dateDifference(start, end) {

  // Copy date objects so don't modify originals

  var s = new Date(start);
  var e = new Date(end);

    var addOneMoreDay = 0;
    if( s.getDay() == 0 || s.getDay() == 6 ) {
    addOneMoreDay = 1;
  }

  // Set time to midday to avoid dalight saving and browser quirks
  s.setHours(12,0,0,0);
  e.setHours(12,0,0,0);

  // Get the difference in whole days
  var totalDays = Math.round((e - s) / 8.64e7);

  // Get the difference in whole weeks
  var wholeWeeks = totalDays / 7 | 0;

  // Estimate business days as number of whole weeks * 5
  var days = wholeWeeks * 5;

  // If not even number of weeks, calc remaining weekend days
  if (totalDays % 7) {
    s.setDate(s.getDate() + wholeWeeks * 7);

    while (s < e) {
      s.setDate(s.getDate() + 1);

      // If day isn't a Sunday or Saturday, add to business days
      if (s.getDay() != 0 && s.getDay() != 6) {
        ++days;
      }
      //s.setDate(s.getDate() + 1);
    }
  }
  var weekEndDays = totalDays - days + addOneMoreDay;
  return weekEndDays;
}

JSFiddle 链接是https://jsfiddle.net/ykxj4k09/2/

const firstDate = new Date("December 30, 2020");
const secondDate = new Date("January 4, 2021");
const daysWithOutWeekEnd = [];
for (var currentDate = new Date(firstDate); currentDate <= secondDate; currentDate.setDate(currentDate.getDate() + 1)) {
  // console.log(currentDate);
  if (currentDate.getDay() != 0 && currentDate.getDay() != 6) {
    daysWithOutWeekEnd.push(new Date(currentDate));
  }
}
console.log(daysWithOutWeekEnd, daysWithOutWeekEnd.length);

虽然此代码可能会解决问题,但包括解释如何以及为何解决问题将真正有助于提高您的帖子质量,并可能导致更多的投票。请记住,您是在为将来的读者回答问题,而不仅仅是现在问的人。编辑您的答案以添加解释并说明适用的限制和假设。
2021-03-31 03:55:29

首先获取一个月的天数

     totalDays(month, year) {
        return new Date(year, month, 0).getDate();
     }

然后通过删除星期六和星期日来获得一个月内的工作日数

  totalWorkdays() {
     var d = new Date(); // to know present date
     var m = d.getMonth() + 1; // to know present month
     var y = d.getFullYear(); // to knoow present year
     var td = this.totalDays(m, y);// to get no of days in a month
     for (var i = 1; i <= td; i++) {  
        var s = new Date(y, m - 1, i);
        if (s.getDay() != 0 && s.getDay() != 6) {
           this.workDays.push(s.getDate());// working days
        }else {
           this.totalWeekDays.push(s.getDate());//week days
         }
      }
      this.totalWorkingDays = this.workDays.length;
 }