views:

1091

answers:

5

I've implemented a stopwatch that works fine without considering that bank holidays and weekends shouldn't be counted in the total duration. I was looking for some open-source library where I could get the elapsed time, passing a start instant, end instant and a set of bank holidays (weekends aren't counted in). The only library that makes me things easier is net.sf.jtemporal, but I have still to amplify the functionality. Could anyone tell me if there is some useful library to get the wanted functionality?

Thanks

A: 

Hi Juan,

Do you only count Bank Hours too? 9AM - 3PM? Or is it 24 hours a day?

Nick Berardi
It's 24 hours a day. I got the elapsed timer but I want to return that duration subtracting the duration of the weekends and bank holidays within that interval.
+1  A: 

As I have mentioned there, probably the best and easiest approach is to create a table containing information about each day (work day count from beginning / bank holiday, etc; one row per day = 365 rows per year) and then just use count function / with proper selection.

Matej
Sorry I've edited my question specifying that the language that I use is Java. Thanks a lot.
+1  A: 

I doubt you can find something that specific. But it's easy enough to create your own logic. Here's some pseudocode...

private long CalculateTimeSpan(DateTime BeginDate, DateTime EndDate, ArrayList<DateTime> BankHollidays)
{
    long ticks = 0;
    while (BeginDate <= EndDate) // iterate until reaching end
    {
        if ((BeginDate is holliday?) || (BeginDate is Weekend?))
             skip;
        else
             ticks += (24*60*60*1000);

        BeginDate = BeginDate + 1 day; // add one day and iterate
    }

    return ticks;
}
I would use a HashSet to avoid putting values repeated, but it seems to me a little inefficient, specially because if the granularity is of seconds you have to iterate 60x60x24 times for each day. Any other more efficient idea for that case. Thanks
A: 

You should take a look at Joda Time. It is a much better date/time API than the one included with Java

Heath Borders
Thanks but I've already done that, and it's better than Java's one but anyway I found net.sf.jtemporal fitter for my goal. As usingCompactPeriodStorage.periodIterator(Period period), you can get CloseableIterator that Iterates over all the periods of the storage that intersects the given period.
A: 

I think this would be a valid solution to what your are looking for. It calculates the elapsed time (considering that one working day has 24 hours) without count the bank holidays and weekends in:

/**
 * Calculate elapsed time in milliseconds
 * 
 * @param startTime
 * @param endTime
 * @return elapsed time in milliseconds
 */

protected long calculateElapsedTimeAux(long startTime, long endTime) { 
 CustomizedGregorianCalendar calStartTime = new CustomizedGregorianCalendar(this.getTimeZone());
 CustomizedGregorianCalendar calEndTime = new CustomizedGregorianCalendar(this.getTimeZone());
 calStartTime.setTimeInMillis(startTime);
 calEndTime.setTimeInMillis(endTime);
 long ticks = 0;

    while (calStartTime.before(calEndTime)) { // iterate until reaching end 
     ticks = ticks + increaseElapsedTime(calStartTime, calEndTime);
    }

    return ticks;
}

private long increaseElapsedTime(CustomizedGregorianCalendar calStartTime, CustomizedGregorianCalendar calEndTime) {
 long interval;
 long ticks = 0;

 interval = HOURS_PER_DAY*MINUTES_PER_HOUR*SECONDS_PER_MIN*MILLISECONDS_PER_SEC; // Interval of one day

 if ( calEndTime.getTimeInMillis() - calStartTime.getTimeInMillis() < interval) {
  interval = calEndTime.getTimeInMillis() - calStartTime.getTimeInMillis();
    }

 ticks = increaseElapsedTimeAux(calStartTime, calEndTime, interval);
 calStartTime.setTimeInMillis(calStartTime.getTimeInMillis() + interval);

 return ticks;
}

protected long increaseElapsedTimeAux(CustomizedGregorianCalendar calStartTime, CustomizedGregorianCalendar calEndTime, long interval) {
 long ticks = 0;

 CustomizedGregorianCalendar calNextStartTime = new CustomizedGregorianCalendar(this.getTimeZone());
 calNextStartTime.setTimeInMillis(calStartTime.getTimeInMillis() + interval);

 if ( (calStartTime.isWorkingDay(_nonWorkingDays) && calNextStartTime.isWorkingDay(_nonWorkingDays)) ) { // calStartTime and calNextStartTime are working days
  ticks = interval;

 }
 else {
  if (calStartTime.isWorkingDay(_nonWorkingDays)) { // calStartTime is a working day and calNextStartTime is a non-working day
   ticks = (calStartTime.getNextDay().getTimeInMillis() - calStartTime.getTimeInMillis());
  }
  else {
   if (calNextStartTime.isWorkingDay(_nonWorkingDays)) { // calStartTime is a non-working day and calNextStartTime is a working day
    ticks = (calNextStartTime.getTimeInMillis() - calStartTime.getNextDay().getTimeInMillis());
   }
   else {} // calStartTime and calEndTime are non-working days
  }
 }

 return ticks;
}