计算两个Date类型参数,相差的小时数。 如果不排除节假日周六日的话,处理起来非常easy,但是…如果要排除法定节假日,排除正常周六日,同时特殊支持法定的工作日(有一些周六日,国家强制正常上班),那么处理起来就非常麻烦,下面用基础的Date和Calendar实现 注意:如果开始或者截止时间属于休息日,对应当天处理小时数为0。例如:2018-2-14 8:00:00 到2018-2-15 10:00:00,2-15是国家规定放假时间,不算时间,只算2-14号的16个小时。可以根据你们自己项目组的需求,灵活的修改哦
/**
* 判断输入的年月日日期是否属于休息日
* @param date 需要判断的日期(年月日)
* @param lawHolidayList 国家规定放假的时间
* @param lawWorkList 国家规定的工作日期
* @return
*/
public static boolean isDayOff(Date date,List lawHolidayList,List lawWorkList){
for(Date date1 :lawHolidayList){
int c = date.compareTo(date1);
if(c==0){
//休息日
return true;
}
}
for(Date date1 :lawWorkList){
int c = date.compareTo(date1);
if(c==0){
//工作日
return false;
}
}
return isZhouLiuZhouRiDate(date);
}
/**
* 判断时间是否属于正常周六日
* @param date
* @return
*/
public static boolean isZhouLiuZhouRiDate(Date date){
Calendar cal = Calendar.getInstance();
cal.setTime(date);
int week = cal.get(Calendar.DAY_OF_WEEK) - 1;
//是否属于周六日
boolean flag = (week == 0 || week == 6);
return flag;
}
/**
* 排除国家法定的休息日、正常周六日,计算两个时间相差多少小时数(休息日当天时间为零处理)
* @param startTimeYYYYMMDDHHMMSS 年月日时分秒
* @param endTimeYYYYMMDDHHMMSS 年月日时分秒
* @param lawHolidayList
* @param lawWorkList
* @return
*/
public static long workHours(Date startTimeYYYYMMDDHHMMSS,
Date endTimeYYYYMMDDHHMMSS,
List lawHolidayList,
List lawWorkList) throws Exception {
//开始时间转成年月日格式
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
String strStartTimeYYYYMMDD = sdf.format(startTimeYYYYMMDDHHMMSS);
Date startTimeYYYYMMDD = sdf.parse(strStartTimeYYYYMMDD);
//开始时间是否属于休息日
boolean startTimeIsDayOff = isDayOff(startTimeYYYYMMDD, lawHolidayList, lawWorkList);
//结束时间转成年月日格式
String strEndTimeYYYYMMDD = sdf.format(endTimeYYYYMMDDHHMMSS);
Date endTimeYYYYMMDD = sdf.parse(strEndTimeYYYYMMDD);
//结束时间是否属于休息日
boolean endTimeIsDayOff = isDayOff(endTimeYYYYMMDD, lawHolidayList, lawWorkList);
//分为4种情况
if (startTimeIsDayOff) {
if (!endTimeIsDayOff) {
//开始时间在休息日里,结束时间不在休息日里(开始那天不计算小时数,结束那天计算小时数)
Calendar cal = Calendar.getInstance();
cal.setTime(startTimeYYYYMMDD);
cal.add(Calendar.DAY_OF_MONTH, +1);
Date validStartTimeYYYYMMDD = cal.getTime();
Date validStartTimeYYYYMMDDTemp = validStartTimeYYYYMMDD;
int skipDay = 0;
//循环遍历开始时间之后的每一个日期
while (validStartTimeYYYYMMDDTemp.compareTo(endTimeYYYYMMDDHHMMSS) != 1) {
if (isDayOff(validStartTimeYYYYMMDDTemp, lawHolidayList, lawWorkList)) {
skipDay += 1;
}
cal.add(Calendar.DAY_OF_MONTH, +1);
validStartTimeYYYYMMDDTemp = cal.getTime();
}
return ((endTimeYYYYMMDDHHMMSS.getTime() - validStartTimeYYYYMMDD.getTime()) / (60 * 60 * 1000)) - skipDay * 24;
} else {
//开始时间在休息日里,结束时间也在休息日里(开始那天不计算小时数,结束那天也不计算小时数,看中间有多少个工作日)
Calendar cal = Calendar.getInstance();
cal.setTime(startTimeYYYYMMDD);
cal.add(Calendar.DAY_OF_MONTH, +1);
Date validStartTimeYYYYMMDD = cal.getTime();
//工作日天数
int workDays = 0;
//循环遍历开始时间之后的每一个日期
while (validStartTimeYYYYMMDD.compareTo(endTimeYYYYMMDDHHMMSS) != 1) {
if (!isDayOff(validStartTimeYYYYMMDD, lawHolidayList, lawWorkList)) {
workDays += 1;
}
cal.add(Calendar.DAY_OF_MONTH, +1);
validStartTimeYYYYMMDD = cal.getTime();
}
return workDays * 24;
}
} else {
if (endTimeIsDayOff) {
int skipDay = 0;
//开始时间不在休息日里,结束时间在休息日里
Calendar cal = Calendar.getInstance();
cal.setTime(startTimeYYYYMMDD);
cal.add(Calendar.DAY_OF_MONTH, +1);
Date validStartTimeYYYYMMDD = cal.getTime();
while (validStartTimeYYYYMMDD.compareTo(endTimeYYYYMMDDHHMMSS) != 1) {
if (!isDayOff(validStartTimeYYYYMMDD, lawHolidayList, lawWorkList)) {
skipDay += 1;
}
cal.add(Calendar.DAY_OF_MONTH, +1);
validStartTimeYYYYMMDD = cal.getTime();
}
Calendar ca = Calendar.getInstance();
ca.setTime(startTimeYYYYMMDDHHMMSS);
int startHour = ca.get(Calendar.HOUR_OF_DAY);
return (24-startHour) + skipDay * 24;
} else {
//开始时间在不在休息日里,结束时间也不在休息日里
int skipDay = 0;
Calendar cal = Calendar.getInstance();
cal.setTime(startTimeYYYYMMDD);
cal.add(Calendar.DAY_OF_MONTH, +1);
Date validStartTimeYYYYMMDD = cal.getTime();
while (validStartTimeYYYYMMDD.compareTo(endTimeYYYYMMDDHHMMSS) != 1) {
if (isDayOff(validStartTimeYYYYMMDD, lawHolidayList, lawWorkList)) {
skipDay += 1;
}
cal.add(Calendar.DAY_OF_MONTH, +1);
validStartTimeYYYYMMDD = cal.getTime();
}
return ((endTimeYYYYMMDDHHMMSS.getTime() - startTimeYYYYMMDDHHMMSS.getTime()) / (60 * 60 * 1000)) - skipDay * 24;
}
}
}
public static void main(String args[]) throws Exception{
SimpleDateFormat yyyyMMdd = new SimpleDateFormat("yyyy-MM-dd");
List lawHolidayDate = new ArrayList();
List lawWorkDate = new ArrayList();
String [] lawHolidayDateStr =
new String[] {
"2018-01-01",
"2018-02-15",
"2018-02-16",
"2018-02-17",
"2018-02-18",
"2018-02-19",
"2018-02-20",
"2018-02-21",
"2018-04-05",
"2018-04-06",
"2018-04-07",
"2018-04-29",
"2018-04-30",
"2018-05-01",
"2018-06-16",
"2018-06-17",
"2018-06-18",
"2018-09-22",
"2018-09-23",
"2018-09-24",
"2018-10-01",
"2018-10-02",
"2018-10-03",
"2018-10-04",
"2018-10-05",
"2018-10-06",
"2018-10-07",
"2018-12-30",
"2018-12-31",
"2019-01-01",
"2019-02-04",
"2019-02-05",
"2019-02-06",
"2019-02-07",
"2019-02-08",
"2019-02-09",
"2019-02-10",
"2019-04-05",
"2019-04-06",
"2019-04-07",
"2019-05-01",
"2019-06-07",
"2019-06-08",
"2019-06-09",
"2019-09-13",
"2019-09-14",
"2019-09-15",
"2019-10-01",
"2019-10-02",
"2019-10-03",
"2019-10-04",
"2019-10-05",
"2019-10-06",
"2019-10-07"};
String [] lawWorkDateStr =
new String[] {
"2018-02-11",
"2018-02-24",
"2018-04-08",
"2018-04-28",
"2018-09-29",
"2018-09-30",
"2018-12-29",
"2019-02-02",
"2019-02-03",
"2019-09-29",
"2019-10-12"};
for(String str :lawHolidayDateStr){
lawHolidayDate.add(yyyyMMdd.parse(str));
}
for(String str :lawWorkDateStr){
lawWorkDate.add(yyyyMMdd.parse(str));
}
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date startDate = sdf.parse("2018-02-22 8:45:10");
Date endDate = sdf.parse("2018-02-24 7:10:10");
System.out.println("相差小时数:"+workHours(startDate,endDate,lawHolidayDate,lawWorkDate));
}
上面的例子,需要在项目里配置两种时间,一是国家法律规定的休息的时间,二是国家规定要正常上班的时间(例如一些周六日,为了十一的一天放假,调休前一个或者后一个周六日必须上班)。上面的例子是直接写死的2018/2019年的两种时间,自己项目的话,可以配置在配置文件或者数据库中
|