Вопрос по java, date – рассчитать рабочие дни, включая праздничные дни

6

Мне нужно рассчитать рабочие дни между двумя датами. Например: у нас выходной (в США) 4 июля. так что если мои даты date1 = 07/03/2012 date2 = 07/06/2012

нет рабочих дней ч / б, эти даты должны быть 1, так как 4 июля - выходной.

У меня есть метод ниже, чтобы рассчитать рабочие дни, которые будут считаться только выходные дни, но не праздники. Есть ли способ рассчитать праздники тоже .... пожалуйста, помогите мне в этом.

  public static int getWorkingDaysBetweenTwoDates(Date startDate, Date endDate) {  
    Calendar startCal;  
    Calendar endCal;  
    startCal = Calendar.getInstance();  
    startCal.setTime(startDate);  
    endCal = Calendar.getInstance();  
    endCal.setTime(endDate);  
    int workDays = 0;  

    //Return 0 if start and end are the same  
    if (startCal.getTimeInMillis() == endCal.getTimeInMillis()) {  
        return 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.SATURDAY   
       && startCal.get(Calendar.DAY_OF_WEEK) != Calendar.SUNDAY) {  
            ++workDays;  
        }  
    } while (startCal.getTimeInMillis() < endCal.getTimeInMillis());  

    return workDays;  
}
Дубликат вопросаDate api for managing off days in an year? но у этого есть лучшие ответы. Basil Bourque
Прежде всего вам понадобится список всех праздничных дней в году, потому что нет занятий по Java (т.е.Locale определенный класс) обеспечивает эту функциональность. Затем вам нужно будет найти, сколько из этого списка попадает между указанными датами, что довольно просто. Затем вы можете удалить это много дней из результата вашего кода выше. WickeD
спасибо за твой ответ. скажем, если у меня есть список, который содержит все праздничные дни, можете ли вы предложить мне, как использовать этот список или как проверить даты этого списка в условии. ran
Вам необходимо следить за информацией о том, какие дни являются выходными, вручную, AFAIK не имеет встроенной функции для этого. Кроме того, кто использует do-while в Java в эти дни? TS-

Ваш Ответ

5   ответов
2

но я провел некоторый поиск для вас и наткнулся на этот поток переполнения стека, в котором есть несколько ссылок на веб-службы, которые могут возвращать вам выходные дни, которые могут помочь вам добраться туда, где вы нужно быть:Веб-сервис национального праздника

Главный ответ в этой теме ссылается на этот веб-сервис:http://www.holidaywebservice.com/

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

Это не слишком излишне. Вы должны получать информацию отsomewhere иначе, как это всегда может быть изменено.
6
Nager.Date

JSON API изNager.Date проект. Поддерживает США, Канаду и Европу. Данные доступны за каждый год, вы можете сохранить информацию в своей собственной базе данных.

Example

//https://github.com/FasterXML/jackson-databind/
ObjectMapper mapper = new ObjectMapper();
MyValue value = mapper.readValue(new URL("http://date.nager.at/api/v1/get/US/2017"), PublicHoliday[].class);

PublicHoliday.class

public class PublicHoliday
{
    public String date;
    public String localName;
    public String name;
    public String countryCode;
    public Boolean fixed;
    public Boolean countyOfficialHoliday;
    public Boolean countyAdministrationHoliday;
    public Boolean global;
    public String[] counties;
    public int launchYear;
}

Пример получения данных JSON.

[
  {
    "date": "2017-01-01",
    "localName": "New Year's Day",
    "name": "New Year's Day",
    "countryCode": "US",
    "fixed": true,
    "countyOfficialHoliday": true,
    "countyAdministrationHoliday": true,
    "global": true,
    "counties": null,
    "launchYear": null
  },
  {
    "date": "2017-01-16",
    "localName": "Martin Luther King, Jr. Day",
    "name": "Martin Luther King, Jr. Day",
    "countryCode": "US",
    "fixed": true,
    "countyOfficialHoliday": true,
    "countyAdministrationHoliday": true,
    "global": true,
    "counties": null,
    "launchYear": null
  },
  {
    "date": "2017-01-20",
    "localName": "Inauguration Day",
    "name": "Inauguration Day",
    "countryCode": "US",
    "fixed": true,
    "countyOfficialHoliday": true,
    "countyAdministrationHoliday": true,
    "global": false,
    "counties": [
      "US-DC",
      "US-LA",
      "US-MD",
      "US-VA"
    ],
    "launchYear": null
  },
  {
    "date": "2017-02-20",
    "localName": "Washington's Birthday",
    "name": "Presidents' Day",
    "countryCode": "US",
    "fixed": true,
    "countyOfficialHoliday": true,
    "countyAdministrationHoliday": true,
    "global": true,
    "counties": null,
    "launchYear": null
  },
  {
    "date": "2017-05-29",
    "localName": "Memorial Day",
    "name": "Memorial Day",
    "countryCode": "US",
    "fixed": true,
    "countyOfficialHoliday": true,
    "countyAdministrationHoliday": true,
    "global": true,
    "counties": null,
    "launchYear": null
  },
  {
    "date": "2017-07-04",
    "localName": "Independence Day",
    "name": "Independence Day",
    "countryCode": "US",
    "fixed": true,
    "countyOfficialHoliday": true,
    "countyAdministrationHoliday": true,
    "global": true,
    "counties": null,
    "launchYear": null
  },
  {
    "date": "2017-09-04",
    "localName": "Labor Day",
    "name": "Labor Day",
    "countryCode": "US",
    "fixed": true,
    "countyOfficialHoliday": true,
    "countyAdministrationHoliday": true,
    "global": true,
    "counties": null,
    "launchYear": null
  },
  {
    "date": "2017-09-09",
    "localName": "Columbus Day",
    "name": "Columbus Day",
    "countryCode": "US",
    "fixed": true,
    "countyOfficialHoliday": true,
    "countyAdministrationHoliday": true,
    "global": false,
    "counties": [
      "US-AL",
      "US-AZ",
      "US-CO",
      "US-CT",
      "US-DC",
      "US-GA",
      "US-ID",
      "US-IL",
      "US-IN",
      "US-IA",
      "US-KS",
      "US-KY",
      "US-LA",
      "US-ME",
      "US-MD",
      "US-MA",
      "US-MS",
      "US-MO",
      "US-MT",
      "US-NE",
      "US-NH",
      "US-NJ",
      "US-NM",
      "US-NY",
      "US-NC",
      "US-OH",
      "US-OK",
      "US-PA",
      "US-RI",
      "US-SC",
      "US-TN",
      "US-UT",
      "US-VA",
      "US-WV"
    ],
    "launchYear": null
  },
  {
    "date": "2017-11-10",
    "localName": "Veterans Day",
    "name": "Veterans Day",
    "countryCode": "US",
    "fixed": false,
    "countyOfficialHoliday": true,
    "countyAdministrationHoliday": true,
    "global": true,
    "counties": null,
    "launchYear": null
  },
  {
    "date": "2017-12-23",
    "localName": "Thanksgiving Day",
    "name": "Thanksgiving Day",
    "countryCode": "US",
    "fixed": true,
    "countyOfficialHoliday": true,
    "countyAdministrationHoliday": true,
    "global": true,
    "counties": null,
    "launchYear": 1863
  },
  {
    "date": "2017-12-25",
    "localName": "Christmas Day",
    "name": "Christmas Day",
    "countryCode": "US",
    "fixed": true,
    "countyOfficialHoliday": true,
    "countyAdministrationHoliday": true,
    "global": true,
    "counties": null,
    "launchYear": null
  }
]
Вы должны следовать соглашениям об именах Java: имена переменных всегда начинаются со строчной буквы.
3

Calendar класс & # x2013; вот мои два цента с использованием нового Java Date and Time API.

Вам нужно откуда-то получить даты праздников, для этого нет стандартной библиотеки Java. Это было бы слишком локализовано в любом случае, так как праздники сильно зависят от вашей страны и региона. (кроме широко известных праздников, таких как Рождество или Пасха).
Вы можете получить их из праздничного API, например. В приведенном ниже коде я жестко закодировал их какList изLocalDates.

Java 9
LocalDate startDate = LocalDate.of(2012, 3, 7);
LocalDate endDate = LocalDate.of(2012, 6, 7);

// I've hardcoded the holidays as LocalDates and put them in a List
final List<LocalDate> holidays = Arrays.asList(
    LocalDate.of(2018, 7, 4)
);

List<LocalDate> allDates =

    // Java 9 provides a method to return a stream with dates from the
    // startdate to the given end date. Note that the end date itself is
    // NOT included.
    startDate.datesUntil(endDate)

        // Retain all business days. Use static imports from
        // java.time.DayOfWeek.*
        .filter(t -> Stream.of(MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY)
            .anyMatch(t.getDayOfWeek()::equals))

        // Retain only dates not present in our holidays list
        .filter(t -> !holidays.contains(t))

         // Collect them into a List. If you only need to know the number of
         // dates, you can also use .count()
        .collect(Collectors.toList());
Java 8

МетодLocalDate.datesUntil недоступен в Java 8, поэтому вы должны получить поток всех дат между этими двумя датами по-разному. Сначала мы должны посчитать общее количество дней междуChronoUnit.DAYS.between метод.

long numOfDaysBetween = ChronoUnit.DAYS.between(startDate, endDate);

Затем мы должны сгенерировать последовательность целых чисел, ровно столько же, сколько количество дней между начальной и конечной датой, а затем создатьLocalDateс этого, начиная с даты начала.

IntStream.iterate(0, i -> i + 1)
    .limit(numOfDaysBetween)
    .mapToObj(startDate::plusDays)

Теперь у нас естьStream<LocalDate>и вы можете использовать оставшуюся часть кода Java 9.

0

который я обнаружил, - это использование математики (заимствование изТАК сообщение):

public static int totalBusinessDaysBetween(LocalDate start, LocalDate end) {
    Objects.requireNonNull(start, "Start date must not be null");
    Objects.requireNonNull(end, "End date must not be null");
    long daysBetweenWithoutWeekends = calculateNumberOfDaysBetweenMinusWeekends(start, end);
    final Set<LocalDate> holidayForYearRange = getUSFederalHolidayForYearRange(start.getYear(), end.getYear());
    for (LocalDate localDate : holidayForYearRange) {
        if (localDate.isAfter(start) && localDate.isBefore(end)) {
            daysBetweenWithoutWeekends--;
        }
    }
    return (int) daysBetweenWithoutWeekends;
}

А также:

private static long calculateNumberOfDaysBetweenMinusWeekends(LocalDate start, LocalDate end) {

    final DayOfWeek startW = start.getDayOfWeek();
    final DayOfWeek endW = end.getDayOfWeek();

    final long days = ChronoUnit.DAYS.between(start, end);
    final long daysWithoutWeekends = days - 2 * ((days + startW.getValue()) / 7);

    //adjust for starting and ending on a Sunday:
    return daysWithoutWeekends + (startW == DayOfWeek.SUNDAY ? 1 : 0) + (endW == DayOfWeek.SUNDAY ? 1 : 0);
}

Я сложил что-то более полноеВот.

Хотя эта ссылка может ответить на вопрос, лучше включить сюда основные части ответа и предоставить ссылку для справки. Ответы, содержащие только ссылки, могут стать недействительными, если связанная страница изменится. -From Review
Спасибо за ответ.
6

что у вас есть список, содержащий все праздники, как вы упоминали.

ArrayList<Integer> holidays = ...

Просто добавьте условие к вашемуif состояние в вашемdo-while:

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

Ради простоты я предположилholiday содержит даты в формате, идентичномCalendar.DAY_OF_YEAR.

Большое спасибо ... я не знаю, как я пропустил эту простую логику. но здесь вместо Calendar.DAY_OF_YEAR я сравниваю его с Calendar.getTime (), который возвращает полную дату. сейчас работает нормально ran
Стоит отметить, что оба примера здесь будут рассчитывать 1 день при разнице в 1 миллисекунду или более. Вместо этого используйте в цикле сравнение дня и года и года.
Ура, рад быть полезным.

Похожие вопросы