我需要计算两个日期之间的营业日。 例如:我们7月4日有假期(在美国)。所以,如果我的日期是 date1 = 07/03/2012 date2 = 07/06/2012
没有工作日b / w这些日期应该是1,因为7月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;
}
答案 0 :(得分: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
相同格式的日期。
答案 1 :(得分:6)
您可以使用JSON API项目的Nager.Date。它支持美国,加拿大和欧洲。您可以将每年可用的数据保存在自己的数据库中。
示例强>
//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
}
]
答案 2 :(得分:3)
由于接受的答案仍然使用过时的Calendar
类-这是我使用新的Java Date and Time API的两分钱。
您必须从某个地方获取假期的日期,没有标准的Java库。毕竟,这将过于本地化,因为假期在很大程度上取决于您所在的国家和地区。 (除了众所周知的假期,例如圣诞节或复活节)。
例如,您可以从假期API中获取它们。在下面的代码中,我将它们硬编码为List
个中的LocalDate
个。
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());
方法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代码的其余部分。
答案 3 :(得分:2)
我没有任何代码示例或类似的东西,但我做了一些搜索,并遇到了这个Stack Overflow线程,它有一些链接到Web服务,可以为你返回假日日期,这可能会帮助你获得到你需要的地方:National holiday web service
该主题中的最佳答案链接到此Web服务:http://www.holidaywebservice.com/
我不确定使用网络服务是否适合这种类型的东西是否过度杀伤,但肯定有更好的方法。我道歉,我不是最有经验的程序员,所以我无法帮助你。
答案 4 :(得分:0)
我发现最快的方法是使用一些数学运算(从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);
}
我把一些更完整的东西放在一起here。