Working with dates (and weekends!) in Javascript

Hi,

Just a quick question, not really sure where to start with this…

Can anyone please point me in the direction of being able to find the number of days between two different dates and weekends in Javascript?

For example, 22nd January to 29th January, this is a 7 day difference, yet the two weekends make it only 5 working days.

Is it possible to allow for weekends in my calculations!?

Thanks

Here is one way.

function bizdays(d1, d2){
	var diff= Math.abs(d1-d2);
	var days= Math.floor(diff/8.64e7); 
	var tem= days%7;
	var weeks= Math.floor(days/7);
	var wd1= d1.getDay();
	var wd2= d2.getDay();
	if(wd1== 6) tem-= 2;
	else if(wd1== 0) tem-= 1;
	if(wd2== 0) tem-= 1;	
	return weeks*5+tem;	
}

var b1=new Date(2009,0,20);
var b2=new Date(2009,1,5);
alert(bizdays(b1,b2))

This only accounts for weekends, you may want to account for holidays as well.

If I understand:


<script type="text/javascript">

var d1=new Date(2009,0,20);
var d2=new Date(2009,1,5);
for(var i=0; d1<d2; ) {
if( d1.getDay() >0 && d1.getDay() <6) i++;
d1.setDate(d1.getDate()+1) ;
}
alert(i);

</script>



<script type="text/javascript">

var d1=new Date(2009,0,20);
var d2=new Date(2009,1,5);
var n=0;
while(d1<d2){
if( d1.getDay() >0 && d1.getDay() <6) n++;
d1.setDate(d1.getDate()+1) ;
}
alert(n); // 12

</script>
 
 
<script type="text/javascript">

Date.prototype.haftaici=function(d2){
var n=0;
while(this<d2){
if( this.getDay() >0 && this.getDay() <6) n++;
this.setDate(this.getDate()+1) ;
}
return n
}

var d1=new Date(2009,0,20);
var d2=new Date(2009,1,5);

var s= d1.haftaici(d2); // 12

alert(s);

</script>

The problem with those solutions is that they loop through all the days between the dates so if the dates are thousands of years apart it will get very slow.

The earlier solution given gets the answer without looping.

Thanks felgall!

I will use mrhoo’s code.

Huge thanks for the great replies guys, some good stuff here.

Think I’ll go with mrhoo’s then; going to give it a go now!

One final question (sorry!) the date picker I’m using has the fields layed out with names like…

date-dd-1

… but this won’t work in Javascript as it doesn’t like picking elements with the dash in them. Anyway around this please? If I rename them, the picker stops working :frowning:

Use the array notation instead


var form = document.getElementById('myForm');
var day = form.elements['date-dd-1'];
...

That worked a treat, many thanks pmw :slight_smile:

Sorry, having a little bit of trouble with this :frowning:

I’ve changed it so that it adds one to the value (if the start date is the same day as the last day they were absent, they’ve been off for a day…) it returns like so…


function datedifference(d1, d2){
	var diff= Math.abs(d1-d2);
	var days= Math.floor(diff/8.64e7); 
	var tem= days&#37;7;
	var weeks= Math.floor(days/7);
	var wd1= d1.getDay();
	var wd2= d2.getDay();
	if(wd1== 6) tem-= 2;
	else if(wd1== 0) tem-= 1;
	if(wd2== 0) tem-= 1;	
	return weeks*5+tem+1;	
}

If I select the start date as ‘Thu Jan 15 00:00:00 UTC 2009’, then select the same end date (Thu Jan 15 00:00:00 UTC 2009) it returns1 days, which is fine.

If I select the next day (Fri Jan 16 00:00:00 UTC 2009), it returns 2, which again is fine, but then it goes a little wrong…

Sat Jan 17 00:00:00 UTC 2009 - returns 3, should return 1 as it’s a weekend
Sun Jan 18 00:00:00 UTC 2009 - returns 3, it’s detecting sunday which is good
Mon Jan 19 00:00:00 UTC 2009 - jumps to 5, not sure why
Tue Jan 20 00:00:00 UTC 2009 - returns 6, should be just four I think
Wed Jan 21 00:00:00 UTC 2009 - returns 7
Thu Jan 22 00:00:00 UTC 2009 - returns 6 (???)
Fri Jan 23 00:00:00 UTC 2009 - returns 7
Sat Jan 24 00:00:00 UTC 2009 - returns 8, but shouldn’t as it’s a weekend
Sun Jan 25 00:00:00 UTC 2009 - returns 8, discounts the Sunday again, which is good
Mon Jan 26 00:00:00 UTC 2009 - returns 10, jumps again on a Monday

… and repeat, huge apologies for the long post, but I’m really a bit stuck, any help would be fantastic, thanks!

Instead of

if(wd1== 6) tem-= 2;
else if(wd1== 0) tem-= 1;
if(wd2== 0) tem-= 1;

Try

if (wd1 > wd2) tem-=2;
if (wd1 == 0 && wd2 == 6) tem--;

If you count from a tuesday and stop on a monday, or thursday to wednesday, for example, there is an odd weekend that needs to be accounted for.

It is simpler to first set any weekend start date to the first business day following the start date, and any weekend end date to the last business day before the end date.
This is the larger part of the code, and is not needed if you do not allow weekends in your date picker

function bizdays(d1, d2){
	var wd1= d1.getDay();
	var wd2= d2.getDay();

// adjust start and end dates
	var n1= wd1== 0? 1: wd1== 6? 2: 0;
	var n2= wd2== 0? -2: wd2== 6? -1: 0;
	if(n1){
		d1.setDate(d1.getDate()+n1);
		wd1= 1;
	}
	if(n2){
		d2.setDate(d2.getDate()+n2);
		wd2= 5;
	}

// calculate week days
	var days= Math.floor((d2-d1)/8.64e7);
	if(days< 0) days= 0;
	var tem= days&#37;7;
	var weeks= Math.floor(days/7);
// catch the odd weekend
	if(wd1> wd2) tem-= 2;

// if you want to subtract holidays, do it now- 
// don't count week end holidays twice!

// return business days
	return weeks*5+tem;
}

// quick test

function testbizdays(n2){
	var D1= new Date(2009, 0, 1);
	var D2= new Date(2009, 0, n2);
	return  D2.toLocaleDateString()+' +'+bizdays(D1, D2)+' biz days';
}

var DA= [], D= new Date(2009, 0, 1),i= 1;
DA[0]= 'Start date: '+D.toLocaleDateString();
while(i< 30){
	DA[DA.length]= testbizdays(i++);
}

alert(DA.join('\
'));