I’m trying to implement a function to calculate the number of working days between 2 dates.
As I’m more a Java programmer than Javascript one I naturally decided to write it in Java. Moreover I found a quite simple solution in Java which should be quite easy to integrate using Java packages in Servoy Developer.
Here is the function:
function GetWorkingDays()
{
var v_calendar_package = Packages.java.util.Calendar;
var v_calendar = new v_calendar_package.getInstance();
var v_date_from = new Packages.java.util.Date(arguments[0]);
v_calendar.setTimeInMillis(arguments[1]);
var v_date_to = v_calendar.getTime();
if (v_date_from == null || v_date_to == null) {
return 0;
}
if (v_date_from.after(v_date_to)) {
var v_temp = v_date_from;
v_date_from = v_date_to;
v_date_to = v_temp;
}
var v_calFrom = new v_calendar_package.getInstance();
v_calFrom.setTime(v_date_from);
var v_calTo = new v_calendar_package.getInstance();
v_calTo.setTime(v_date_to);
var v_iNoOfWorkingDays = 0;
do {
if (v_calFrom.get(v_calendar_package.DAY_OF_WEEK) != v_calendar_package.SATURDAY
&& v_calFrom.get(v_calendar_package.DAY_OF_WEEK) != v_calendar_package.SUNDAY) {
v_iNoOfWorkingDays++;
}
v_calFrom.add(v_calendar_package.DATE, 1);
} while (v_calFrom.getTimeInMillis() < v_calTo.getTimeInMillis());
application.output("Working days between "+arguments[0]+" and "+arguments[1]+" = "+v_iNoOfWorkingDays+" days");
return v_iNoOfWorkingDays;
}
My first issue is to convert the date from JavaScript to Java on this line:
var v_date_from = new Packages.java.util.Date(arguments[0]);
I get an error because Java doesn’t seem to like a date in JavaScript?! When I print the dates (arg0 and arg1) they look like that “Fri Sep 18 00:00:00 BST 2009”.
I have tried to convert them in millisec and use the Java Date constructor with millisec but I get the following error:
Cannot convert Thu Oct 15 00:00:00 BST 2009 to java.lang.Long
My code was ```
var v_date_from = new Packages.java.util.Date(arguments[0].getTime());
I could parse the dates to extract the year, month and day but I find it quite annoying and would like to know if there is not an easier way to do it?
Maybe it can even be done in full Javascript but unfortunately I'm not an expert <img src="{SMILIES_PATH}/icon_sad.gif" alt=":(" title="Sad" />
Btw if you see any other problems in this code (I'm sure there are much more), feel free to tell me <img src="{SMILIES_PATH}/icon_wink.gif" alt=";-)" title="Wink" />
So I would like to know
To progress I’ve used the Java Date constructor with Year, Month, Day. It works to create Date objects
However I don’t seem to be able to call a method from my Date object ?!
My Date object is declared like that:
var v_date_from = new Packages.java.util.Date(v_temp_date_year, v_temp_date_month, v_temp_date_day);
Hi,
I’ve been doing a lot of stuff with dates and have these globals I call, the first gives you what you want
// calculateworkingdays(startDate, endDate)
var stDate = new Date(arguments[0]);
var enDate = new Date(arguments[1]);
var startDateYear = stDate.getFullYear();
var startDateMonth = stDate.getMonth();
var startDateDat = stDate.getDate();
var endDateYear = enDate.getFullYear();
var endDateMonth = enDate.getMonth();
var endDateDat = enDate.getDate();
var ssDate = new Date(startDateYear,startDateMonth,startDateDat);
var eeDate = new Date(endDateYear,endDateMonth,endDateDat);
if (ssDate > eeDate)
{
return -1;
}
var workingdays = 0 ;
while (ssDate <= eeDate)
{
if(ssDate.getDay()!=0 && ssDate.getDay()!=6)
{
workingdays++;
}
//ssDate = new Date(ssDate.valueof()+86400000);
ssDate = new Date(ssDate.getFullYear(), ssDate.getMonth(), ssDate.getDate() + 1 ) ;
}
return workingdays - 1 ;
I also needed to be able to add & subtract a certain number of workings days to/from a date
// this routine will add working days to a date
// myDate = startingdate, days = no. working days to add.
var myDate = arguments[0] ;
var days = arguments[1] ;
if(!myDate) return ;
var temp_date = new Date() ;
var i = 0 ;
var days_to_add = 0 ;
while ( i < ( days ) )
{
days_to_add += 1 ;
temp_date = new Date( myDate.getTime() + (days_to_add * 24 * 60 * 60 * 1000) );
// 0 = Sunday, 6 = Saturday, if the date not equals a weekend day then increase by 1
if ( ( temp_date.getDay() != 0 ) && ( temp_date.getDay() != 6 ) )
{
i += 1 ;
}
}
return new Date( myDate.getTime() + days_to_add * 24 * 60 * 60 * 1000 ) ;
// this routine will subtract working days to a date
// myDate = startingdate
// days = no. working days to subtract
var myDate = arguments[0] ;
var days = arguments[1] ;
//need to negate value if it is positive
if ( days > 0 )
{
// need to make it 1 less
days -= 1 ;
days = days * -1 ;
}
else // it's negative, so increment by 1
{
days += 1 ;
}
if(!myDate) return ;
var temp_date = new Date() ;
var i = 0 ;
var days_to_add = 0 ;
while ( i >= ( days ) )
{
days_to_add -= 1 ;
temp_date = new Date( myDate.getTime() + (days_to_add * 24 * 60 * 60 * 1000) );
// 0 = Sunday, 6 = Saturday, if the date not equals a weekend day then decrease by 1
if ( ( temp_date.getDay() != 0 ) && ( temp_date.getDay() != 6 ) )
{
i -= 1 ;
}
}
return new Date( myDate.getTime() + days_to_add * 24 * 60 * 60 * 1000 ) ;
Interesting. Thanks for the info.
I’ve just tried to get it, but the registration form doesn’t seem to post the details. I get a blank page as if it stopped half-way through
EDIT: Actually it worked! I just received 3 emails with the download link and licence key
patrick:
Thanks for reporting (empty page)! I will fix this asap.
No problem.
However the plugin will not help me I think, I’m afraid
I need to detect which day (e.g. “Sunday”) it is for a given date. I would need a function like getDayName(“26-03-2010”)
It’s this bit in my code:
do {
if (v_calFrom.get(v_calendar_package.DAY_OF_WEEK) != v_calendar_package.SATURDAY
&& v_calFrom.get(v_calendar_package.DAY_OF_WEEK) != v_calendar_package.SUNDAY) {
v_iNoOfWorkingDays++;
}
v_calFrom.add(v_calendar_package.DATE, 1);
} while (v_calFrom.getTimeInMillis() < v_calTo.getTimeInMillis());
Foobrother:
However the plugin will not help me I think, I’m afraid
I need to detect which day (e.g. “Sunday”) it is for a given date. I would need a function like getDayName(“26-03-2010”)
If I am not mistaken Rafi gave you a fully functional method in pure JavaScript. Why don’t you use that ?
getDayName() is actually available for DateTime objects in the DateUtils plugin. It delivers “Sunday” if English is your locale.
I could also enhance the plugin to deliver an array of “working” days between two dates. The question is: what is a working day? Monday through Saturday? Should I make Saturday an option? What if you are Muslim or Jewish? Any thoughts?
If I am not mistaken Rafi gave you a fully functional method in pure JavaScript. Why don’t you use that ?
Oooh yes, I didn’t notice that post! I thought it was my last one with all the quote and and pieces of code
Will check that.
Thanks for telling me
patrick:
getDayName() is actually available for DateTime objects in the DateUtils plugin. It delivers “Sunday” if English is your locale.
I could also enhance the plugin to deliver an array of “working” days between two dates. The question is: what is a working day? Monday through Saturday? Should I make Saturday an option? What if you are Muslim or Jewish? Any thoughts?
Ok, I’ll check this DateTime class.
I understand that including a working days functions is not easy because of all the reasons you have mentioned. When I was searching for some code doing it was the same issue. Some were including both dates in the count others not, others just the start day etc…
What might be useful is to enhance a plugin method called createDateSeries(). That creates an array from start to end. I could add an optional parameter Number daysToExclude. That way you could pass [6, 7] for example and the series created would then not contain Saturdays and Sundays.
patrick:
What might be useful is to enhance a plugin method called createDateSeries(). That creates an array from start to end. I could add an optional parameter Number daysToExclude. That way you could pass [6, 7] for example and the series created would then not contain Saturdays and Sundays.
Yes this solution would be very flexible in fact. You could have a 2 working days week (my dream )
OK. The next version of the DateUtils plugin will have a method called getWorkingDays(Date start, Date end, Number nonWorkingDays). You can call it like this:
It seems to work. However when you have the same date for start/end I have a problem. It returns 0
You will tell me that it’s stupid to calculate for one day. But I use this system for holidays management. So people might want to take only 1 day off.
Here is the code I use (I want start/end days to be included):
var days = plugins.DateUtils.getWorkingDays(new Date(arguments[0]), new Date(arguments[1]), [6,7]);
return (days.length) - 1;
patrick:
That was actually the only question. Should the first date given be included or not? So I guess it should. I will change that and send you an update.
With your new changes it does seem to count Sunday as a day off. When I do a test with Start on Monday and End on Sunday it says 6 days, if I do from Saturday to Sunday it says 1 day and if I do from Friday to Monday it says 3 days.
However if I try from Monday to Saturday it says 5 days or Monday to Monday it says 1 day
Here is the code I use:
var days = plugins.DateUtils.getWorkingDays(new Date(arguments[0]), new Date(arguments[1]), [6,7]);
return (days.length);