1

I'm trying to find workday count between two dates (weekend and time have to ignore). I'm using following function to do that. But it is giving false results for multiple condition like if startdate is on weekend or enddate is on weekend. Here is one example for demo that giving one extra day in count.

2018-03-08 00:00:00.0 and 2018-04-22 01:37:29.887

Count returning 32 (Should be 31, it is considering 23-04-2018 as well). Please provide some perfect solution/approach to do the same.

private static int calculateDuration(Date startDate, Date endDate)
{
  Calendar startCal = Calendar.getInstance();
  startCal.setTime(startDate);
  startCal.set( Calendar.HOUR_OF_DAY, 0 );
  startCal.set( Calendar.MINUTE, 0 );
  startCal.set( Calendar.SECOND, 0 );
  startCal.set( Calendar.MILLISECOND, 0 );
  Calendar endCal = Calendar.getInstance();
  endCal.setTime(endDate);
  endCal.set( Calendar.HOUR_OF_DAY, 0 );
  endCal.set( Calendar.MINUTE, 0 );
  endCal.set( Calendar.SECOND, 0 );
  endCal.set( Calendar.MILLISECOND, 0 );
  int workDays = 0;

  if (startCal.getTimeInMillis() > endCal.getTimeInMillis())
  {
    startCal.setTime(endDate);
    endCal.setTime(startDate);
  }

  do
  {
    startCal.add(Calendar.DAY_OF_MONTH, 1);
    System.out.println("************"+Calendar.DAY_OF_WEEK);
    System.out.println("Before weekend condition"+Calendar.DAY_OF_WEEK+"Workdays="+workDays);

    if (startCal.get(Calendar.DAY_OF_WEEK) != Calendar.SATURDAY && startCal.get(Calendar.DAY_OF_WEEK) != Calendar.SUNDAY)
    {
      workDays++;
        System.out.println("This day picked "+startCal.getTime()+"Workdays="+workDays);


    }
  }
  while (startCal.getTimeInMillis() <= endCal.getTimeInMillis());
System.out.println("Final workdays count for  "+startDate+" and "+endDate+" is"+workDays);

  return workDays;
}

I have tried multiple solutions but this worked well except mentioned scenario.

Ole V.V.
  • 81,772
  • 15
  • 137
  • 161
nik
  • 1,464
  • 4
  • 18
  • 32
  • 3
    I recommend use of LocalDate/LocalDateTime and read https://stackoverflow.com/questions/25747499/java-8-calculate-difference-using-appropriate-time-units-between-two-localdat – Bogdan Lukiyanchuk Apr 22 '18 at 06:16
  • 32 is correct, by the way. – Jacob G. Apr 22 '18 at 06:17
  • This has been asked and answered more than once before. Sorry, I don’t easily find an original, but you can see if your search abilities are better than mine. – Ole V.V. Apr 22 '18 at 07:36
  • Should the count include first and/or last day (provided they are working days)? – Ole V.V. Apr 22 '18 at 07:44
  • @OleV.V. - Start date should be excluded and end date should be included in count. – nik Apr 25 '18 at 05:53

1 Answers1

8

I highly recommend using the java.time.LocalDate::datesUntil method found in Java 9 and later. It only takes a couple lines to calculate, rather than having to use Calendar:

var startDate = LocalDate.parse("2018-03-08");
var endDate = LocalDate.parse("2018-04-22");

var numWeekDays = startDate.datesUntil(endDate)
                           .map(LocalDate::getDayOfWeek)
                           .filter(d -> d != DayOfWeek.SATURDAY && d != DayOfWeek.SUNDAY)
                           .count();

System.out.println(numWeekDays);

Output:

32
Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
Jacob G.
  • 28,856
  • 5
  • 62
  • 116
  • 3
    If you statically import `SATURDAY` and `SUNDAY` and use `EnumSet` you can even write `EnumSet weekend = EnumSet.of(SATURDAY, SUNDAY)` and `EnumSet weekdays = EnumSet.complementOf(weekend)` and then do `.filter(weekdays::contains)` for some really clean code. :) – David Conrad Apr 22 '18 at 07:13