получить количество рабочих дней в конкретном месяце

java

1750 просмотра

5 ответа

Я хочу получить количество рабочих дней в конкретном месяце

в моем случае выходные дни пятница и суббота

Я использую этот код:

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;

public class TestWeekDay {

    /**
     * @param args
     * @throws ParseException 
     */
    public static void main(String[] args) throws ParseException {

        // TODO Auto-generated method stub


        SimpleDateFormat sdf = new SimpleDateFormat("dd-MM-yyyy");
        String dateInString = "01-07-2016";
        Date startDate = sdf.parse(dateInString);
        String dateInString2 = "31-07-2016";
        Date endDate = sdf.parse(dateInString2);
        calculateDuration(startDate,endDate);

    }



    public static int calculateDuration(Date startDate, Date endDate)
    {
      Calendar startCal = Calendar.getInstance();
      startCal.setTime(startDate);

      Calendar endCal = Calendar.getInstance();
      endCal.setTime(endDate);

      int workDays = 0;

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

      do
      {
        startCal.add(Calendar.DAY_OF_MONTH, 1);
        if (startCal.get(Calendar.DAY_OF_WEEK) != Calendar.FRIDAY && startCal.get(Calendar.DAY_OF_WEEK) != Calendar.SATURDAY)
        {
          workDays++;
        }
      }
      while (startCal.getTimeInMillis() <= endCal.getTimeInMillis());

      return workDays;
    }

}

когда я тестирую, например, на июль месяц, у меня 22, и правильный ответ должен быть 21

Автор: franco Источник Размещён: 06.11.2019 04:58

Ответы (5)


1 плюс

Решение

Я думаю, что ваша проблема может быть вызвана граничным условием, которое приводит к добавлению одного дополнительного дня к каждому месяцу перед оценкой. Попробуйте сделать день недели проверки первым , прежде чем увеличивать фактический день.

while (startCal.getTimeInMillis() <= endCal.getTimeInMillis()) {
    if (startCal.get(Calendar.DAY_OF_WEEK) != Calendar.FRIDAY &&
        startCal.get(Calendar.DAY_OF_WEEK) != Calendar.SATURDAY) {

        workDays++;
    }

    startCal.add(Calendar.DAY_OF_MONTH, 1);
}
Автор: Tim Biegeleisen Размещён: 18.07.2016 06:36

3 плюса

Если вы добавите следующую строку после ifоператора, вы увидите свою проблему.

System.out.printf("%s  %d%n", new SimpleDateFormat("yyyy-MM-dd EEE").format(startCal.getTime()), workDays);

Кстати: это называется отладкой .

Выход

2016-07-02 Sat  0
2016-07-03 Sun  1
2016-07-04 Mon  2
2016-07-05 Tue  3
2016-07-06 Wed  4
2016-07-07 Thu  5
2016-07-08 Fri  5
2016-07-09 Sat  5
2016-07-10 Sun  6
2016-07-11 Mon  7
2016-07-12 Tue  8
2016-07-13 Wed  9
2016-07-14 Thu  10
2016-07-15 Fri  10
2016-07-16 Sat  10
2016-07-17 Sun  11
2016-07-18 Mon  12
2016-07-19 Tue  13
2016-07-20 Wed  14
2016-07-21 Thu  15
2016-07-22 Fri  15
2016-07-23 Sat  15
2016-07-24 Sun  16
2016-07-25 Mon  17
2016-07-26 Tue  18
2016-07-27 Wed  19
2016-07-28 Thu  20
2016-07-29 Fri  20
2016-07-30 Sat  20
2016-07-31 Sun  21
2016-08-01 Mon  22
22

Как видите, у вас есть две проблемы:

  • Первый день месяца (2016-07-01) не проверен
  • Первый день следующего месяца (2016-08-01) проверен

Я оставлю это вам, чтобы найти решение. Удачи.

Автор: Andreas Размещён: 18.07.2016 07:02

1 плюс

Calendar cal = Calendar.getInstance();
/* set the 1st date of ongoing month */
cal.set(cal.get(Calendar.YEAR), cal.get(Calendar.MONTH), 1, 0, 0, 1);
Calendar cal1 = Calendar.getInstance();
/* set the last date of ongoing month */
cal1.set(cal1.get(Calendar.YEAR), cal1.get(Calendar.MONTH), cal1.getMaximum(Calendar.DAY_OF_MONTH), 23, 59, 59);
int workingDays = 0;
/* run the while loop until the months are same */
while (cal.get(Calendar.MONTH) != cal1.get(Calendar.MONTH)) {
      if (cal.get(Calendar.DAY_OF_WEEK) != Calendar.SUNDAY
           && cal.get(Calendar.DAY_OF_WEEK) != Calendar.SATURDAY) {
                System.out.println("Check >> "+ cal.getTime());
                workingDays++;
      }
      cal.add(Calendar.DAY_OF_MONTH, 1);
}
System.out.println(workingDays);
Автор: Aayush Shrivastava Размещён: 28.04.2017 04:59

0 плюса

Используйте этот кусок кода, просто запустите цикл, пока условие не startCal after endCalвернет false.

while(!startCal.after(endCal)) {
      if (startCal.get(Calendar.DAY_OF_WEEK) != Calendar.FRIDAY && startCal.get(Calendar.DAY_OF_WEEK) != Calendar.SATURDAY) {
        workDays++;
      }
      startCal.add(Calendar.DATE, 1);
  }
Автор: Arjit Размещён: 18.07.2016 06:59

-1 плюса

Замените <= в вашем состоянии while на <, как показано ниже -

while (startCal.getTimeInMillis() < endCal.getTimeInMillis());

Это создает проблему, потому что в последний день месяца ваше условие (первоначально с <=) возвращает true, потому что в конце после увеличения startCal на 1 день оно становится равным endCal в точке. Из-за того, что вы стали равны, ваша следующая строка выполняется в do

startCal.add(Calendar.DAY_OF_MONTH, 1);

и поэтому следующая дата - 1 апреля, то есть понедельник. И, таким образом, это добавляется в список рабочих дней тоже.

ПРИМЕЧАНИЕ. Пожалуйста, следуйте комментариям @Andreas для отладки вашего кода. С небольшой отладкой вы могли бы легко найти проблему. И снова отладка кода очень важна для разработчиков. Вы не можете просто игнорировать это!

Как справедливо указывает @Andreas, 1-й день месяца тоже не будет проверяться. Чтобы проверить 1-й день, сначала нужно сравнить 1-й день, а затем увеличить день на 1. Ниже приведен код -

 do
   {
      if (startCal.get(Calendar.DAY_OF_WEEK) != Calendar.FRIDAY &&   startCal.get(Calendar.DAY_OF_WEEK) != Calendar.SATURDAY)
      {
          workDays++;
      }
      startCal.add(Calendar.DAY_OF_MONTH, 1); //Moved this line to last of do block
   }
   while (startCal.getTimeInMillis() < endCal.getTimeInMillis());
Автор: Manish Размещён: 18.07.2016 06:53
Вопросы из категории :
32x32