After revisiting this script, and some modifications, the following is available to allow a user to add a feature that calculates the expected delivery date.
Change line 7 from
ship.setDate( safety ); // add a number of days
to
ship.setDate( ship.getDate() + safety );
The problem was that you want to add days, not set days.
Thanks for your input guys, I had a long hard re-think over the approach I was making for this and came up with this little number...
var businessDays = 7, counter = 0; // set to 1 to count from next business day
while( businessDays>0 ){
var tmp = new Date();
var startDate = new Date();
tmp.setDate( startDate .getDate() + counter++ );
switch( tmp.getDay() ){
case 0: case 6: break;// sunday & saturday
default:
businessDays--;
};
}
The idea was to start with the business days and count backwards to zero for each day encountered that fell in to the range of a business day. This use of switch would enable a person to declare a day in the week as a non-business day, for example someone may not work on a monday, therefore the addition of case:1 would include a monday.
This is a simple script and does not take in to account public or bank holidays, that would be asking for a much more complex script to work with.
The result is a date that is set to the date of shipping, the user can then extract the date info in any format that they please, eg.
var shipDate = tmp.toUTCString().slice(1,15);
Your main problem was that adding safety each time meant you were adding multiple days each time it looped, instead of 1. So first loop = 1, second = 1+2, etc.
I believe this works as you'd like:
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);
I just found this script which is working nice, you can give an optional array for your country's holidays
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());
}
I've adapted Mark Giblin's revised code to better deal with end of year dates and also U.S. federal holidays. See below...
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;
}
ship.setDate( safety ); // add a number of days
Doesn't add days. It sets the day. More info
The
setDate()
method sets the day of theDate
object relative to the beginning of the currently set month.
If you want to add days do something like this:
ship.setDate(ship.getDate()+1);