如何在JavaScript中添加工作日?

时间:2014-01-23 01:01:25

标签: javascript

var businessDays = 10; // this will come from a form
var counter = 0;  // I have a counter
var safety = 0;  // I have a safety variable
var ship = today = new Date();  // I have the current date and an initialized shipping variable but the buy date will come from a form

while( ++safety <30 ){
ship.setDate( safety );  // add a number of days
switch( ship.getDay() ){

    case 0: // Sunday
    case 6: // Saturday

    break;

    default:
        counter++;
    }

if( counter >= businessDays ) break;

}

// the expected shipping date

console.log(">>> today = " + today);
console.log(">>> days  = " + businessDays);
console.log(">>> ship = " + ship);

问题是:如果我在eBay上买东西,他们说发货时间是7到10个工作日,而且我在交货前的日期和工作日,我应该得到一个有效的日期,但我不是。我的日期是从今年1月开始,而不是从购买之日起的7到10个工作日

8 个答案:

答案 0 :(得分:7)

我已经改编了Mark Giblin的修订代码,以更好地处理年终日期以及美国联邦假期。见下文......

function businessDaysFromDate(date,businessDays) {
  var counter = 0, tmp = new Date(date);
  while( businessDays>=0 ) {
    tmp.setTime( date.getTime() + counter * 86400000 );
    if(isBusinessDay (tmp)) {
      --businessDays;
    }
    ++counter;
  }
  return tmp;
}

function isBusinessDay (date) {
  var dayOfWeek = date.getDay();
  if(dayOfWeek === 0 || dayOfWeek === 6) {
    // Weekend
    return false;
  }

  holidays = [
    '12/31+5', // New Year's Day on a saturday celebrated on previous friday
    '1/1',     // New Year's Day
    '1/2+1',   // New Year's Day on a sunday celebrated on next monday
    '1-3/1',   // Birthday of Martin Luther King, third Monday in January
    '2-3/1',   // Washington's Birthday, third Monday in February
    '5~1/1',   // Memorial Day, last Monday in May
    '7/3+5',   // Independence Day
    '7/4',     // Independence Day
    '7/5+1',   // Independence Day
    '9-1/1',   // Labor Day, first Monday in September
    '10-2/1',  // Columbus Day, second Monday in October
    '11/10+5', // Veterans Day
    '11/11',   // Veterans Day
    '11/12+1', // Veterans Day
    '11-4/4',  // Thanksgiving Day, fourth Thursday in November
    '12/24+5', // Christmas Day
    '12/25',   // Christmas Day
    '12/26+1',  // Christmas Day
  ];

  var dayOfMonth = date.getDate(),
  month = date.getMonth() + 1,
  monthDay = month + '/' + dayOfMonth;

  if(holidays.indexOf(monthDay)>-1){
    return false;
  }

  var monthDayDay = monthDay + '+' + dayOfWeek;
  if(holidays.indexOf(monthDayDay)>-1){
    return false;
  }

  var weekOfMonth = Math.floor((dayOfMonth - 1) / 7) + 1,
      monthWeekDay = month + '-' + weekOfMonth + '/' + dayOfWeek;
  if(holidays.indexOf(monthWeekDay)>-1){
    return false;
  }

  var lastDayOfMonth = new Date(date);
  lastDayOfMonth.setMonth(lastDayOfMonth.getMonth() + 1);
  lastDayOfMonth.setDate(0);
  var negWeekOfMonth = Math.floor((lastDayOfMonth.getDate() - dayOfMonth - 1) / 7) + 1,
      monthNegWeekDay = month + '~' + negWeekOfMonth + '/' + dayOfWeek;
  if(holidays.indexOf(monthNegWeekDay)>-1){
    return false;
  }

  return true;
}

答案 1 :(得分:1)

感谢您的投入,我对我为此制作的方法进行了长时间的重新思考,并提出了这个小数字......

var businessDays = 7, counter = 0; // set to 1 to count from next business day
while( businessDays>0 ){
    var tmp = new Date();
    tmp.setDate( tmp.getDate() + counter++ );
    switch( tmp.getDay() ){
            case 0: case 6: break;// sunday & saturday
            default:
                businessDays--;
            }; 
}

这个想法是从工作日开始,并且在遇到的每一天都倒数到零,这一天都落到了工作日的范围内。这种切换的使用将使一个人能够将一周中的一天宣布为非工作日,例如某人可能不在星期一工作,因此增加案例:1将包括星期一。

这是一个简单的脚本,并不考虑公共或银行假期,这将要求使用更复杂的脚本。

结果是设置为发货日期的日期,然后用户可以以他们喜欢的任何格式提取日期信息,例如

var shipDate = tmp.toUTCString().slice(1,15);

答案 2 :(得分:1)

我们的UI默认搜索输入为上一个工作日或一周前。 这是向前和向后都有效的东西。

// add (or subtract) business days to provided date
addBusinessDays = function (startingDate, daysToAdjust) {
    var newDate = new Date(startingDate.valueOf()),
        businessDaysLeft,
        isWeekend,
        direction;

    // Timezones are scary, let's work with whole-days only
    if (daysToAdjust !== parseInt(daysToAdjust, 10)) {
        throw new TypeError('addBusinessDays can only adjust by whole days');
    }

    // short-circuit no work; make direction assignment simpler
    if (daysToAdjust === 0) {
        return startingDate;
    }
    direction = daysToAdjust > 0 ? 1 : -1;

    // Move the date in the correct direction
    // but only count business days toward movement
    businessDaysLeft = Math.abs(daysToAdjust);
    while (businessDaysLeft) {
        newDate.setDate(newDate.getDate() + direction);
        isWeekend = newDate.getDay() in {0: 'Sunday', 6: 'Saturday'};
        if (!isWeekend) {
            businessDaysLeft--;
        }
    }
    return newDate;
};

传递一个可选的假日数据结构并调整它也很容易。

但是,生成假日数据结构,这将需要更多的努力,不仅针对每个国家和地区,而且针对每个组织。

答案 3 :(得分:0)

ship.setDate( safety );  // add a number of days

不添加天数。它设定了一天。更多信息:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/setDate

如果您想添加日期,请执行以下操作:

ship.setDate(ship.getDate()+1);

答案 4 :(得分:0)

更改第7行
ship.setDate( safety );  // add a number of days

ship.setDate( ship.getDate() + safety );

问题在于您要添加天,而不是设置天数。

答案 5 :(得分:0)

你的主要问题是每次增加安全性意味着你每次循环都会增加多天,而不是1.所以第一次循环= 1,第二次= 1 + 2等等。

我相信这可以按你的意愿运作:

var businessDays = 10; // this will come from a form
var counter = 0;  // I have a counter
var safety = 0;  // I have a safety variable
var ship = today = new Date();  // I have the current date and an initialized shipping variable but the buy date will come from a form
console.log(">>> today = " + today);
// now the loop...

while( ++safety <30 ){
ship.setDate(ship.getDate()+1 );
switch( ship.getDay() ){

    case 0: // Sunday
    case 6: // Saturday

    break;

    default:
        counter++;
    }

if( counter >= businessDays ) break;

}
  // add a number of days
// the expected shipping date


console.log(">>> days  = " + businessDays);
console.log(">>> ship = " + ship);

答案 6 :(得分:0)

我需要类似但有所不同的东西,这就是我想出的。

对于每个有假期的月份,将假期添加到具有一个键的对象中。然后,该键在该月中有一系列被视为假期的天。

function getDueDate(date) {

    var numBusinessDays = 20;

    var saturday = 6;
    var sunday = 0;

    var holidays = {

        /* Months are zero-based. 0 = Jan, 11 = Dec */
        0: [1, 2],
        1: [6],
        3: [24],
        11: [25, 26]

    };

    var dayOfWeek = null;
    var dayOfMonth = null;
    var month = null;
    var isWeekday = null;
    var monthHolidays = null;
    var isHoliday = null;

    while (numBusinessDays > 0) {

        dayOfWeek = date.getDay();
        dayOfMonth = date.getDate();
        month = date.getMonth();
        isWeekday = dayOfWeek !== saturday && dayOfWeek !== sunday;
        monthHolidays = holidays[month];

        isHoliday = monthHolidays
            ? monthHolidays.indexOf(dayOfMonth) > -1
            : false;

        if (isWeekday && !isHoliday) --numBusinessDays;

        date.setDate(dayOfMonth + 1);

    }

    return date;

}

答案 7 :(得分:0)

我刚刚发现此脚本运行良好,可以为您所在国家/地区的假期提供可选数组

function addBusinessDays(date, days, holidays) {
    var calendar = java.util.Calendar.getInstance();
    calendar.setTimeInMillis(date.getTime());
    var numberOfDaysToAdd = Math.abs(days);
    var daysToAdd = days < 0 ? -1 : 1;
    var businessDaysAdded = 0;


    function isHoliday(dateToCheck) {
        if (holidays && holidays.length > 0) {
            for (var i = 0; i < holidays.length; i++) {
                if (holidays[i].getFullYear() == dateToCheck.get(java.util.Calendar.YEAR) && holidays[i].getMonth() == dateToCheck.get(java.util.Calendar.MONTH) && holidays[i].getDate() == dateToCheck.get(java.util.Calendar.DAY_OF_MONTH)) {
                    return true;
                }
            }
        }
        return false;
    }

    while (businessDaysAdded < numberOfDaysToAdd) {
        calendar.add(java.util.Calendar.DATE, daysToAdd);
        if (calendar.get(java.util.Calendar.DAY_OF_WEEK) == java.util.Calendar.SATURDAY || calendar.get(java.util.Calendar.DAY_OF_WEEK) == java.util.Calendar.SUNDAY) {
            // add another day
            continue;
        }
        if (isHoliday(calendar)) {
            // add another day
            continue;
        }
        businessDaysAdded ++;
    }

    return new Date(calendar.getTimeInMillis());
}