Main Topics
Browse All TopicsI'm trying to find the best way, in term of performance, to get a number of days between two dates with saturday & sunday excluded.
Currently, I have one to loop through all days between them to check & count.
Any better idea?
Thanks
This Question has been solved and asker verified All Experts Exchange premium technology solutions are available to subscription members.
Experts Exchange has been collecting answers to technology questions since 1996…3 million and counting! If you have a question, chances are we already have your answer.
If you can't find the exact answer you're looking for, ask our exclusive community of 50,000 experts. You’ll get a personalized answer from a trusted professional.
Thousands of free tech tips, tricks, how-to’s and tutorials are available in our peer reviewed articles section. See for yourself how smart our experts are, no login required.
Access the answers to your technology questions today.
30-day free trial. Register in 60 seconds.
Members of the expert community talk about why the experience at Experts Exchange is different than what you will find anywhere else.

Try it out and discover for yourself.
30-day free trial. Register in 60 seconds.
Join the community of experts here and help other tech pros by answering question in your area of expertise. You can earn FREE access to all Experts Exchange's premium features and resources.
you can speed your loop up by having your loop jump 7 days at a time (adding 5 to the counter each time) until there are less than 7 days remaining. then going one day at a time.
Actually you can avoid having a loop altogether by just making 3 calcs
- number of full week + number of days before first full week + number of days after last full week.
Thanks you all experts for quick response. I much appreciate all of you.
I'm now interested in calculation way than looping since it seems to be faster, but I do not understand in some parts of code in the links and need time to test them for valid/performance. The concept should be as objects described, I think.
I will come back soon with solutions and point split, or some problems. hehe
Regards
Another thought :
Just first subtract the dates from one another to get the total number of days. Divide that by 7 and double the resulting int, to give you the number of weekend days. Then mod your total number of days by 7 (which can only result in 1-6), and make a short loop to test each of these 1-6 days for weekendedness, adding that tally to the 7-int'd calc, remembering that you won't know - or care - whether the mod days are before, or after, your period.
Here's the code (using ints 1-7 for days of the week instead of a calendar), based on the above model I described :
.
.
private float start, end, result;
private int daynum=0;
private int[] days;
.
.
.
start = 10;
end = 31;
days = new int[(int)(end-start)];
for (int a=0;a<end-start;a++){
days[a]=++daynum;
if(daynum==7){daynum=0;}
}
result = (end-start)/7;
result = (int)result*2;
if ((int)(end-start)%7>0){
System.out.println("Extra days beyond a full week = "+((int)end-start)%7);
}
for(int y=0;y<(int)((end-start)%7)
if(days[(int)((end-start)-
result+=1;
}
}
System.out.println("The total number of working days between dates is "+((int)(end-start)-(int)r
.
.
.
>>I'm trying to find the best way, in term of performance ...
above code, but now working on 1,400 years worth of days, (starting a day 10), now with a timer which starts *after* the days' array is up and available.
start = 10;
end = 511000;//about 1,400 years worth of days ;)
days = new int[(int)(end-start)];
for (int a=0;a<end-start;a++){
days[a]=++daynum;
if(daynum==7){daynum=0;}
}
long starttime = System.nanoTime();
result = (end-start)/7;
result = (int)result*2;
for(int y=0;y<(int)((end-start)%7)
if(days[(int)((end-start)-
result+=1;
}
}
long endtime = System.nanoTime();
System.out.println("The total number of working days between dates is "+((int)(end-start)-(int)r
if(((endtime-starttime)/10
else {System.out.println("This calculation took "+(endtime-starttime)+" nanoseconds");}
Thanks for your try, krakatoa.
I wrote a class to test in 4 ways using GregorianCalendar with GMT timezone to avoid DST offset problem.
It's attached below.
way1 - my own looping through all days
way2 - using calculation in link of Bart_Cr
way3 - using krakatoa's calculation
way4 - boost up looping as objects's suggest
At the final of R&D, I ended up with the way4 since it seems to be most valid and fairly speed.
One more issue, what I need is counting days not finding the different number. If both the same day, it should result in 1 not 0.
Here is the result of R&D
Start End Method Days Time(msec) Result Note
==========================
2008/01/04 2008/01/04 way1 1 It's Friday
way2 1
way3 0 !?
way4 1
2008/01/05 2008/01/05 way1 0 It's Saturday
way2 1 !?
way3 0
way4 0
2008/01/06 2008/01/06 way1 0 It's Sunday
way2 0
way3 0
way4 0
2008/01/01 2008/01/31 way1 23 Jan 2008
way2 23
way3 22 !?
way4 23
2008/02/01 2008/02/29 way1 21 Feb 2008
way2 21
way3 20 !?
way4 21
2000/01/01 4000/01/01 way1 521775 2153 2,000 years
way2 521776 0 !?
way3 521775 10
way4 521775 551
2000/01/01 4001/01/01 way1 522297 2153 2,001 years
way2 522297 0
way3 522298 10 !?
way4 522297 551
2000/01/01 4005/01/01 way1 523080 2163 2,005 years
way2 523081 0 !?
way3 523080 10
way4 523080 551
!? = seems to be wrong #days
It would be great if the calculation ways give the right result, but I cann't figure for the right algorithm.
I used the following loop to compare the result with way2. It's exactly the same. So, I assummed you solution is the best since it takes the result in ~0 msec for 2,000 years. That's great!
ct.set1(2000,0,1);
for(int i=2000; i<=4000; i++) {
ct.set2(i,0,1);
int a = ct.way4();
int b = ct.way2();
if(a != b) System.out.println(i+" !?");
else if(i%100==0) System.out.println(i);
try{Thread.sleep(0);}catch
}
Thanks
You didn't stick to anything like the framework when it came to timings:
long startTime = System.currentTimeMillis()
final long ONE_HOUR = 60 * 60 * 1000L;
long totalDays = (gc2.getTimeInMillis() - gc1.getTimeInMillis() + ONE_HOUR) / (ONE_HOUR * 24);
int dayNum = 0;
int[] days = new int[(int)totalDays];
for (int a=0; a<totalDays; ++a) {
days[a] = ++dayNum;
if(dayNum == 7) { dayNum = 0; }
}
The whole point of the for loop here was simply to set up an array of ints that could be used instead of dates - *to test the algorithm* **NOT** the acquisition of the dates themselves!! You put the timer **upstream** of this initialisation - what kind of sense does that make??!
OK, I should have trusted you to do the trivial part yourself, and obtain the dates (the number of days); but as you didn't, here is the full code - plus the results from a test on 4,000 years - you should have run to make a test against other methods:
import java.util.*;
import java.text.*;
public class SatSunlessDays {
private float start, end, result;
private int daynum=0;
private int[] days;
private long totdays;
public static void main(String[] args){
new SatSunlessDays();
}
public SatSunlessDays (){
Date d1 = new GregorianCalendar(1973,11,
Date d2 = new GregorianCalendar(5973,11,
long diff = d2.getTime() - d1.getTime();
totdays = (diff / (1000*60*60*24));
days = new int[(int)(totdays)];
long starttime = System.nanoTime(); // THIS IS WHERE THE TIMERS SHOULD START
result = (totdays)/7;
result = ((int)result)*2;
for(int y=0;y<(int)((totdays)%7);y
if(days[(int)((totdays)-(y
result+=1;
}
}
long endtime = System.nanoTime();//TIMERS
System.out.println("Number
System.out.println("The total number of working days between dates is "+((int)(totdays)-(int)res
if(((endtime-starttime)/10
else {System.out.println("This calculation took "+(endtime-starttime)+" nanoseconds");}
}
}
C:\jdk1.5\>java SatSunlessDays
Number of days in period is 1460970.
The total number of working days between dates is 1043550
This calculation took 7823 nanoseconds
i.e.:
import java.util.*;
import java.text.*;
// Span - 4,000 years.
public class SatSunlessDays {
private float result;
private long totdays;
public static void main(String[] args){
new SatSunlessDays();
}
public SatSunlessDays (){
GregorianCalendar gd1 = new GregorianCalendar(1973,11,
GregorianCalendar gd2 = new GregorianCalendar(5973,12,
Date d1 = new GregorianCalendar(1973,11,
Date d2 = new GregorianCalendar(5973,12,
long diff = d2.getTime() - d1.getTime();
totdays = (diff / (1000*60*60*24));
long starttime = System.nanoTime(); // TIMER STARTS HERE
result = (int)((totdays/7)*2);
for(int y=0;y<(int)((totdays)%7);y
if((gd2.get(Calendar.DAY_O
System.out.println(gd2.get
result+=1;
}
}
long endtime = System.nanoTime(); // TIMER ENDS HERE
System.out.println("Number
System.out.println("The total number of working days between dates is "+((int)(totdays)-(int)res
if(((endtime-starttime)/10
else {System.out.println("This calculation took "+(endtime-starttime)+" nanoseconds");}
}
}
CEHJ:
>For testing, you can scale the tests by using multiple invocations and taking the average
Yes, that's the estimate of everage. I'm using Editplus to modify the code and there are hot keys to compile & run easily. At least ten times for each solution running (uncomment one by one), but no matter how many times since I got a working/validated code with a nice time running than my origin code. I just don't want to get a headache on other solutions anymore.
krakatoa:
>You put the timer **upstream** of this initialisation - what kind of sense does that make??!
As your code does not act on dates but integer, I was trying to apply the algorithm to dates but not quite understand it. On the basic lookup, I saw two 'for' loops and both use days as a shared var. If there is no first loop, what the second loop shall be. So, I thought that the whole code is a unit and should be under the start time capture. Besides, I can't get the applied code (from your algorithm) to make the right result.
I do not test your last code yet, but is this code really working?
gd2.get(Calendar.DAY_OF_WE
>>I just don't want to get a headache on other solutions anymore.
I thought you were both an expert (on the leaderboard), and cognizant of the fact that solving other people's problems gives you a headache, rather than the other way around.
The point of my posts was, as I have repeated several times, that the speed resides in the fact that the biggest loop you will ever have to evaluate, no matter how big the time period, is 6 - this being the maximum number of days needed to look back on form the end date to see if any were Saturdays or Sundays!
gnoon, re: but is this code really working?
Yes.
Both pieces of code below are now fully working. I'm posting twice: first is the code without any debugs and with an if conditional, to run as fast as possible; second post uses a switch case and debugs, so you can see in the dark.
Again, I don't believe the code you awarded on compares with this. Where are the dates and the looping for it? There are none. You can run the tests.
I put the timer *after* the 'acquisition' of the dates because that part is the responsibility of Java, not the algorithm. Obviously, you're welcome to do the same for any other code - as I wouldn't want to be accused of gerrymandering.
Yes, you're right (6-being the maximum number of days remained by mod 7), but (1)there are three groups to concern within #total days (the first week, middle week(s), and the last week) and (2)the 1st date of each month is *not* always on Monday.
Here is what I see from your algorithm:
totalDays = end - start
weeks = totalDays / 7
satsunDays = weeks * 2 //<-- (1) here is what I need a period of time to prove is it true and what if totaldays is 2 and both are sat. and sun.
remainDays = totalDays % 7
satsunDays += FN(remainDays) //<-- (2) It's hard to imagine for the function to find # of sat. & sun.
result = totalDays - satsunDays //<-- (3) the result is a blurred figure
Look at Bart_Cr's code, he is finding only positive # of days and get result
days -= firstDOW - lastDOW;
If firstday and lastday are not SUN or SAT Then
days++;
End If
This is amazing code I ever seen. It's simple but completly beautiful just like Newton's formula (F=ma). That's.
Thanks
gnoon:
>> ... but (1)there are three groups to concern within #total days (the first week, middle week(s), and the last week) and (2)the 1st date of each month is *not* always on Monday. ...<<
1. You mentioned **absolutely none** of this in your question. You asked for the number of days without Sats and Suns - no mention of splitting anything - come on!
2. If by " .. *not* always a Monday ..." you are referring to anything to do with my code, then I'm afraid you just don't understand the first thing about what I'm trying to say with this algorithm. Let me repeat it once more :
******ANY******* contiguous set of days always includes a Saturday and a Sunday if the size of that set is equal to any multiple of 7 - ****IRRESPECTIVE**** of which day of the week (M,T,W,T,F,S,S) that period starts on. You threfore know, with cast-iron certainty, that the only calculation that needs to be made to find the number of Saturdays and Sundays in any date range is to see how many times it divides by 7, and then **ONLY** examine each day of any modulus remainder for whether any of those days are weekend days -- BACKWARDS, FROM THE LAST DATE. Underlined.
3. As to bart_cr's code : firstly, it isn't his code *anyway*, so I don't see why you are so enamoured with what he's contributed with that - in fact it's plagiarism. Secondly, when it comes to testing it, you have code there which works on ******no dates at all, bar one****** without any looping, and timed in some incompatible way that it renders the test useless.
4. My pathology is :
> a) find total number of days;
> b) divide integrally by 7 to get weeks, and double that for the Sat/Sun count;
> c) mod the total days by 7, to see if any what part of a week (days) remains;
> d) from the end date, examine each c) date back from there for Sat/Sun
> e) if you find a Sat / Sun in d), add it to the doubled-up value already in b).
>>> As to bart_cr's code : firstly, it isn't his code *anyway*
It is my code, code that I've written a few years ago for a plugin I've written for IntelliJ idea. As you can see in the comments of the commited code and the name of the committer, they're not incidentally all "BartCr". I just didn't want to simply copy paste the code which would not get this comment.
And it is code that works for the problem stated, at a good speed. I'm not going to discuss which code is fastest because with benchmarks you can prove everything or nothing. I to can state that starting the time should be done 3 lines later in my code, but I don't see why I should.
The fact is that the code I provided works fast enough and after fixing the bug that was originally in there did give the correct results for all date ranges at always the same speed.
@Bart_cr
>> for a plugin I've written for IntelliJ idea
Really? And you just happened to notice a bug when you trotted it out for some l'il ole EE question, right?
As for the rest of your comment, this is exactly the spirit of dismissiveness that got this question into the mess it was as it was closing - you don't have the committment to put your claims to the test properly, as I have done in my code.
Stick the timers anywhere you like - as long as mine are in the same place! Let's say - as I've said umpteen times - ***after the acquisition of the dates*** since that acquisition is neither here nor there when it comes to the engine code and its speed. And anyway, LOL, the point you missed completely is that the quintessence of what my solution offers is so no-brainingly obvious that it only needs a tiny loop to accommodate it - IOW time's arrow runs one way - there'll always be a Sat and Sun in ***any*** 7 -day block.
:¬P
>>> Really? And you just happened to notice a bug when you trotted it out for some l'il ole EE question, right?
Nope, I didn't notice the bug, gnoon pointed out the bug with his first test class. The way I use the class in my code never ever lets a period end on a saturday. That's why in the plugin the bug has never been a problem.
And further, I wouldn't have had any problem with a point split, or even you getting all the points. I'm here to answer questions, solve problems, not for getting points or whatever. I'm not that competitive, I just love Java. Been loving it for 11 years now.
As for your code. I like the approach to solving the problem. I didn't think of that way when I originally developed the code. The other two solutions I also had implemented at one time, but they simply lacked the needed performance. The only problem I still had with your code when the question was closed, was (probably as the poster) that it was not clear to me how it should be implemented. BTW, I'm still not sure how to write a method providing two dates and returning one single int with the result using your method, starting out from where you state the timer should start.
>> BTW, I'm still not sure how to write a method providing two dates and returning one single int with the result using your method, starting out from where you state the timer should start. <<
Well, that's another question entirely, and has no bearing on the natural history of how time works - which for once in its miserable life smiles on the programmer.
I appreciate very much you seeing what I was getting at now. Unlike you, I had no reason to tackle this question beforehand, and therefore had to bring the pathology together in some kludgy and buggy earlier code postings - which nevertheless still embodied (but masked) the mod-7 principle.
Like you, I dont mind particularly about the points, but somehow the currency of them plays a role, otherwise a few good and possibly helpful efforts can go unnoticed. I don't make *that* many posts, but when I do, I llike to think they'll end up being correct as well as helping someone who appreciates them. That's the only place where the points come in for me.
I agree about timers, and it's a very probably large and unresolvable area of contention - I'm no expert. But one thing I would say is that if one has to work with the rather arcane (and I'm sure well-founded) Java machinery to work with Dates (hence my downbeat comment above), that that should be left out of the timing considerations since no algorithm on Earth is going to circumvent what amounts to hard-wired convention.
Out of interest, I hacked your class and ran it. It's a good piece of kit. If you have any interest, the results from how it ran against mine are :
C:\jdk1.5\gbjava>java DateUtil
The time taken in nans was 2997588
42
C:\jdk1.5\gbjava>java SatSun
Number of days in period is 60.
The total number of working days between dates is 42
Number of Saturdays and Sundays in this period is 18
This calculation took 65093 nanoseconds
.
.
and that was including more System.outs than your code. However, it would be immensely interesting to know, community-wise, what monsters we'd both fabricated.
:) k.
[
To any future visitor to this question: You should ignore my code and remarks in these comments:
ID:21411561 Author:krakatoa
ID:21411986 Author:krakatoa
04.23.2008 at 11:17AM BST, ID: 21419017
04.23.2008 at 12:26PM BST, ID: 21419367
noting that this one overrides all previous :
04.24.2008 at 03:15AM BST, ID: 21427284
]
I've never used NetBeans in a real project, so I'm not going to comment on that.
For me, I slightly prefer IntelliJ over Eclipse. I think Eclipse is probably richer in the area of features, but the learning curve is a bit steeper. IntelliJ contains enough features for me to work and what I really like is that IntelliJ allows each user to use the features he know and likes and all you don't have to bother about the rest.
Business Accounts
Answer for Membership
by: CEHJPosted on 2008-04-22 at 01:58:55ID: 21409124
You're probably using the best way. You need to use Calendar to avoid time variation pitfalls