Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/jquery/75.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 如何使用Moment.js排除两个日期之间的周末_Javascript_Jquery_Momentjs - Fatal编程技术网

Javascript 如何使用Moment.js排除两个日期之间的周末

Javascript 如何使用Moment.js排除两个日期之间的周末,javascript,jquery,momentjs,Javascript,Jquery,Momentjs,我试图在JavaScript代码中排除周末。我使用moment.js,很难为“days”选择正确的变量 到目前为止,我认为需要通过将工作日变量从第1天改为第5天来排除第6天(星期六)和第0天(星期日)。但不确定它是如何变化的 我的JSFIDLE如下所示: HTML: <div id="myContent"> <input type="radio" value="types" class="syncTypes" name="syncTypes"> <td><

我试图在JavaScript代码中排除周末。我使用moment.js,很难为“days”选择正确的变量

到目前为止,我认为需要通过将工作日变量从第1天改为第5天来排除第6天(星期六)和第0天(星期日)。但不确定它是如何变化的

我的JSFIDLE如下所示:

HTML

<div id="myContent">
<input type="radio" value="types" class="syncTypes" name="syncTypes"> <td><label for="xshipping.xshipping1">Free Shipping: (<span id="fsv1" value="5">5</span> to <span id="fsv2" value="10">10</span> working days)</label> </td><br>
    <div id="contacts" style="display:none;border:1px #666 solid;padding:3px;top:15px;position:relative;margin-bottom:25px;">     
    Contacts
</div>
<input type="radio" value="groups" class="syncTypes" name="syncTypes"> <td><label for="xshipping.xshipping2">Express Shipping: (<span id="esv1" value="3">3</span> to <span id="esv2" value="4">4</span> working days)</label> </td>    
<div id="groups" style="display:none;border:1px #666 solid;padding:3px;top:15px;position:relative">     
    Groups
</div>
</div>
var a = 5; //Free shipping between a
var b = 10;//and b
var c = 3;//Express shipping between c
var d = 4;//and d    
var now = moment();    
var f = "Your item will be delivered between " + now.add("days",a).format("Do MMMM") + " and " + now.add("days",b).format("Do MMMM");
var g = "Your item will be delivered between " + now.add("days".c).format("Do MMMM") + " and " + now.add("days",d).format("Do MMMM");

var h = document.getElementById('contacts');
h.innerHTML = g

var i = document.getElementById('groups');
i.innerHTML = f

$(function() {
    $types = $('.syncTypes');
    $contacts = $('#contacts');
    $groups = $('#groups');
    $types.change(function() {
        $this = $(this).val();
        if ($this == "types") {
            $groups.slideUp(300);
            $contacts.delay(200).slideDown(300);
        }
        else if ($this == "groups") {
            $contacts.slideUp(300);
            $groups.delay(200).slideDown(300);
        }
    });
});

我建议在矩原型中添加一个函数

也许是这样的?(未经测试)

nextWeekday:函数(){
var day=this.clone(this);
天=天。添加('天',1);
while(day.weekday()==0 | | day.weekday()==6){
天=天。添加(“天”,1);
}
回归日;
},
n工作日:函数(n){
var day=this.clone(this);
对于(var i=0;i给你

function addWeekdays(date, days) {
  date = moment(date); // use a clone
  while (days > 0) {
    date = date.add(1, 'days');
    // decrease "days" only if it's a weekday.
    if (date.isoWeekday() !== 6 && date.isoWeekday() !== 7) {
      days -= 1;
    }
  }
  return date;
}
你这样叫它

var date = addWeekdays(moment(), 5);
我使用了
.isoWeekday
而不是
.weekday
,因为它不依赖于区域设置(
.weekday(0)
可以是周一或周日)

不要减去工作日,即
addWeekdays(矩(),-3)
否则这个简单的函数将永远循环


更新的JSFIDLE(使用不同的momentjs cdn)

这些迭代循环解决方案不适合我的需要。 他们的速度太慢,不适合大量使用。 所以我做了自己的版本:


希望您觉得它很有用。

如果您想要一个版本的@acorio代码示例,它性能良好(使用@Isantos的优化),并且可以处理负数,请使用以下方法:

moment.fn.addWorkdays = function (days) {
  // Getting negative / positive increment
  var increment = days / Math.abs(days);
  // Looping weeks for each full 5 workdays
  var date = this.clone().add(Math.floor(Math.abs(days) / 5) * 7 * increment, 'days');
  // Account for starting on Saturdays and Sundays
  if(date.isoWeekday() === 6) { date.add(-increment, 'days'); }
  else if(date.isoWeekday() === 7) { date.add(-2 * increment, 'days'); }
  // Adding / removing remaining days in a short loop, jumping over weekends
  var remaining = days % 5;
  while(remaining != 0) {
    date.add(increment, 'days');
    if(date.isoWeekday() !== 6 && date.isoWeekday() !== 7)
      remaining -= increment;
  }
  return date;
};
请看这里的小提琴:


编辑:现在修复了一个问题:最初在周末一天增加5天

如果你想要一个纯JavaScript版本(不依赖于Moment.js),试试这个

function addWeekdays(date, days) {
    date.setDate(date.getDate());
    var counter = 0;
        if(days > 0 ){
            while (counter < days) {
                date.setDate(date.getDate() + 1 ); // Add a day to get the date tomorrow
                var check = date.getDay(); // turns the date into a number (0 to 6)
                    if (check == 0 || check == 6) {
                        // Do nothing it's the weekend (0=Sun & 6=Sat)
                    }
                    else{
                        counter++;  // It's a weekday so increase the counter
                    }
            }
        }
    return date;
}
此函数会检查第二天是否在周六(第6天)或周日(第0天)。如果为真,则计数器不会增加,但日期会增加。 此脚本适用于较小的日期增量,如一个月或更短的时间。

momentJS插件可能对类似任务有所帮助

它不能解决确切的问题,但能够计算范围内的特定工作日

用法:

moment().isoWeekdayCalc({  
  rangeStart: '1 Apr 2015',  
  rangeEnd: '31 Mar 2016',  
  weekdays: [1,2,3,4,5], //weekdays Mon to Fri
  exclusions: ['6 Apr 2015','7 Apr 2015']  //public holidays
}) //returns 260 (260 workdays excluding two public holidays)

我知道这个问题很久以前就发布了,但如果有人对此有意见,这里有一个使用moment.js的优化解决方案:

function getBusinessDays(startDate, endDate){
  var startDateMoment = moment(startDate);
  var endDateMoment = moment(endDate)
  var days = Math.round(startDateMoment.diff(endDateMoment, 'days') - startDateMoment .diff(endDateMoment, 'days') / 7 * 2);
  if (endDateMoment.day() === 6) {
    days--;
  }
  if (startDateMoment.day() === 7) {
    days--;
  }
  return days;
}
const calcBusinessDays=(d1、d2)=>{
//计算所有使用天数,包括最后一天(第+1天)
施工天数=d2.差异(d1,'天')+1;
console.log('Days:',Days);
//在此时间跨度内发生了多少个完整的周末
常数周末=数学楼层(天/7);
console.log('完整周末:',周末);
//减去所有周末
营业日=天-(周末*2);
//7周以内的特殊情况
如果(周末===0){
const cur=d1.clone();
for(设i=0;i
d1和d2是作为参数传递给
calculateBusinessDays

calculateBusinessDays(d1, d2) {
    const days = d2.diff(d1, "days") + 1;
    let newDay: any = d1.toDate(),
    workingDays: number = 0,
    sundays: number = 0,
    saturdays: number = 0;
    for (let i = 0; i < days; i++) {
        const day = newDay.getDay();
        newDay = d1.add(1, "days").toDate();
        const isWeekend = ((day % 6) === 0);
        if (!isWeekend) {
            workingDays++;
        } 
        else {
            if (day === 6) saturdays++;
            if (day === 0) sundays++;
        }
    }
        console.log("Total Days:", days, "workingDays", workingDays, "saturdays", saturdays, "sundays", sundays);
    return workingDays;
}
计算营业日(d1、d2){
施工天数=d2.差异(d1,“天数”)+1;
让newDay:any=d1.toDate(),
工作日:编号=0,
星期日:数量=0,
星期六:数字=0;
for(设i=0;i
这可以在两个日期之间不循环的情况下完成

// get nb of weekend days
var startDateMonday = startDate.clone().startOf('isoWeek');
var endDateMonday = endDate.clone().startOf('isoWeek');

var nbWeekEndDays = 2 * endDateMonday.diff(startDateMonday, 'days') / 7;
var isoDayStart = startDate.isoWeekday();
if (isoDayStart > 5) // starts during the weekend
{
    nbWeekEndDays -= (8 - isoDayStart);
}
var isoDayEnd = endDate.isoWeekday();
if (isoDayEnd > 5) // ends during the weekend
{
    nbWeekEndDays += (8 - isoDayEnd);
}

// if we want to also exlcude holidays
var startOfStartDate = startDate.clone().startOf('day');
var nbHolidays = holidays.filter(h => {
    return h.isSameOrAfter(startOfStartDate) && h.isSameOrBefore(endDate);
}).length;

var duration = moment.duration(endDate.diff(startDate));
duration = duration.subtract({ days: nbWeekEndDays + nbHolidays });

var nbWorkingDays = Math.floor(duration.asDays()); // get only nb of complete days

如果不支持仅工作日,那么查找上周日的第一个星期一并执行周*7-周*2并添加之前的工作日如何还有尾随的workdaysa、b、c、d、f、g、h、i……这将使代码可读且可维护。由于交付时间是固定的,有没有办法使用if语句。对于免费送货:if todaysDate=Monday->firstDate=todaysDate+7天)lastDate=todaysDate+14天。但我假设一周中的每一天都要这样做?很好。我现在使用了这个版本。但我已经修改为:
var inc=days/Math.abs(days);
将while条件更新为
days!=0
,并将
1
的出现次数更改为
inc
。通过这种方式,我可以“添加”负数的工作日。问题是它使用循环,因此不会扩展while循环。谢谢!但是
date=date.add(1,'days'))
可以是
date.add(1,'days');
因为时刻实例是可变的,所以…我如何添加两个时刻对象并使用它只获取工作日?@ppumkin:也有,但它没有diff函数。@BillyTom现在有businessDiffHey@dain我不明白这个
var increment=days/Math.abs(days);
它将始终为1,对吗?@csaiki否,以防
天数
为负数(即你想减少天数)那么它将是-1有意义的!谢谢=)这段代码有问题。如果今天是星期六,我加了5天,那么我将得到下个星期六而不是星期五。星期天也是如此。我如何处理这个问题?@RotimiBest在5年后发现错误这是不好的。如果开始日期是星期一,结束日期是3天后(星期四),结果是
const calcBusinessDays = (d1, d2) => {
    // Calc all days used including last day ( the +1 )
    const days = d2.diff(d1, 'days') + 1;

    console.log('Days:', days);

    // how many full weekends occured in this time span
    const weekends = Math.floor( days / 7 );

    console.log('Full Weekends:', weekends);

    // Subtract all the weekend days
    let businessDays = days - ( weekends * 2);

    // Special case for weeks less than 7
    if( weekends === 0 ){
    const cur = d1.clone();
    for( let i =0; i < days; i++ ){
        if( cur.day() === 0 || cur.day() === 6 ){
        businessDays--;
        }
        cur.add(1, 'days')
    }
    } else {
    // If the last day is a saturday we need to account for it
    if (d2.day() === 6 ) {
        console.log('Extra weekend day (Saturday)');
        businessDays--;
    }
    // If the first day is a sunday we need to account for it
    if (d1.day() === 0) {
        console.log('Extra weekend day (Sunday)');
        businessDays--;
    }
    }

    console.log('Business days:', businessDays);
    return businessDays;
}
calculateBusinessDays(d1, d2) {
    const days = d2.diff(d1, "days") + 1;
    let newDay: any = d1.toDate(),
    workingDays: number = 0,
    sundays: number = 0,
    saturdays: number = 0;
    for (let i = 0; i < days; i++) {
        const day = newDay.getDay();
        newDay = d1.add(1, "days").toDate();
        const isWeekend = ((day % 6) === 0);
        if (!isWeekend) {
            workingDays++;
        } 
        else {
            if (day === 6) saturdays++;
            if (day === 0) sundays++;
        }
    }
        console.log("Total Days:", days, "workingDays", workingDays, "saturdays", saturdays, "sundays", sundays);
    return workingDays;
}
// get nb of weekend days
var startDateMonday = startDate.clone().startOf('isoWeek');
var endDateMonday = endDate.clone().startOf('isoWeek');

var nbWeekEndDays = 2 * endDateMonday.diff(startDateMonday, 'days') / 7;
var isoDayStart = startDate.isoWeekday();
if (isoDayStart > 5) // starts during the weekend
{
    nbWeekEndDays -= (8 - isoDayStart);
}
var isoDayEnd = endDate.isoWeekday();
if (isoDayEnd > 5) // ends during the weekend
{
    nbWeekEndDays += (8 - isoDayEnd);
}

// if we want to also exlcude holidays
var startOfStartDate = startDate.clone().startOf('day');
var nbHolidays = holidays.filter(h => {
    return h.isSameOrAfter(startOfStartDate) && h.isSameOrBefore(endDate);
}).length;

var duration = moment.duration(endDate.diff(startDate));
duration = duration.subtract({ days: nbWeekEndDays + nbHolidays });

var nbWorkingDays = Math.floor(duration.asDays()); // get only nb of complete days