10

2つの日付の間の営業日を計算する必要があります。例:7月4日に(米国で)休日があります。したがって、私の日付がdate1 = 07/03/2012 date2 =07/06/2012の場合

7月4日は休日であるため、これらの日付のb/wの営業日は1にする必要があります。

週末のみをカウントし、休日はカウントしない営業日を計算するための以下の方法があります。休日を計算する方法もありますか....これについて私を助けてください。

  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;  
}
4

5 に答える 5

12

受け入れられた回答はまだ廃止されたクラスを使用しているため、パッケージCalendarで利用可能な新しいJava Date andTimeAPIを使用した2セントです。java.time

休日の日付はどこかから取得する必要があります。標準のJavaライブラリはありません。休日は国や地域に大きく依存するため、とにかくローカライズされすぎます(クリスマスやイースターなどの広く知られている休日を除く)。
たとえば、ホリデーAPIから取得できます。Set以下のコードでは、それらをのとしてハードコーディングしていLocalDateます。

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 Set
final Set<LocalDate> holidays = Set.of(
    LocalDate.of(2018, 7, 4)
);
// For the sake of efficiency, I also put the business days into a Set.
// In general, a Set has a better lookup speed than a List.
final Set<DayOfWeek> businessDays = Set.of(
    MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY
);

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 -> businessDays.contains(t.getDayOfWeek()))

        // 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はJava8では使用できないため、これら2つの日付の間のすべての日付のストリームを異なる方法で取得する必要があります。ChronoUnit.DAYS.between最初に、メソッドを使用する間の合計日数をカウントする必要があります。

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

次に、開始日と終了日の間の日数とまったく同じ長さの整数のシーケンスを生成しLocalDate、開始日から開始して、そこからsを作成する必要があります。

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

これでStream<LocalDate>、が作成され、Java9コードの残りの部分を使用できるようになりました。また、Java 8では使用できないため、の使用法を置き換える必要がありSet.of()ます。おそらく。によってnew HashSet<>(Arrays.asList(MONDAY...FRIDAY))

于 2018-11-26T09:47:45.763 に答える
9

あなたが言ったように、あなたがすべての休日を含むリストを持っているとしましょう。

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

于 2012-06-01T16:53:35.090 に答える
8

Nager.Date

Nager.DateプロジェクトのJSONAPIを使用できます。米国、カナダ、ヨーロッパをサポートしています。毎年利用可能なデータは、独自のデータベースに情報を保存できます。

//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
  }
]
于 2017-02-09T21:27:10.937 に答える
3

コードサンプルなどはありませんが、検索を行ったところ、休日の日付を返すことができるWebサービスへのリンクが含まれているこのStack Overflowスレッドに出くわしました。これにより、目的地にたどり着くことができます。必要なもの:国民の祝日Webサービス

そのスレッドのトップアンサーは、このWebサービスにリンクしています:http ://www.holidaywebservice.com/

この種のことにWebサービスを使用するのがやり過ぎかどうかはわかりませんが、もっと良い方法があることは確かです。申し訳ありませんが、私は最も経験豊富なプログラマーではないため、私が望むほどあなたを助けることはできません。

于 2012-06-01T16:37:37.510 に答える
1

私が見つけた最速の方法は、いくつかの数学を使用することです(SOの投稿から借りています):

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);
}

ここでもっと完全なものをまとめました。

于 2018-11-29T14:12:12.093 に答える