java 排除法定节假日以及正常周六日,计算两个Date相差的小时数
項(xiàng)目組有一個(gè)需求,計(jì)算兩個(gè)Date類型參數(shù),相差的小時(shí)數(shù)。業(yè)務(wù)上有一些特殊的用途,可能用于績(jī)效考核的目的吧…
如果不排除節(jié)假日周六日的話,處理起來非常easy,是個(gè)程序員都能寫出來,但是…如果要排除法定節(jié)假日,排除正常周六日,同時(shí)特殊支持法定的工作日(有一些周六日,國(guó)家強(qiáng)制正常上班),那么處理起來就非常麻煩,我耗時(shí)大概1天半的時(shí)間,用基礎(chǔ)的Date和Calendar實(shí)現(xiàn),下面是具體的實(shí)現(xiàn)代碼,要是有更好的實(shí)現(xiàn),歡迎大家留言。
注意:項(xiàng)目組要求如果開始或者截止時(shí)間屬于休息日,對(duì)應(yīng)當(dāng)天處理小時(shí)數(shù)為0。例如:2018-2-14 8:00:00 到2018-2-15 10:00:00,2-15是國(guó)家規(guī)定放假時(shí)間,不算時(shí)間,只算2-14號(hào)的16個(gè)小時(shí)。可以根據(jù)你們自己項(xiàng)目組的需求,靈活的修改哦
/*** 判斷輸入的年月日日期是否屬于休息日* @param date 需要判斷的日期(年月日)* @param lawHolidayList 國(guó)家規(guī)定放假的時(shí)間* @param lawWorkList 國(guó)家規(guī)定的工作日期* @return*/public static boolean isDayOff(Date date,List<Date> lawHolidayList,List<Date> 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);}/*** 判斷時(shí)間是否屬于正常周六日* @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;}/*** 排除國(guó)家法定的休息日、正常周六日,計(jì)算兩個(gè)時(shí)間相差多少小時(shí)數(shù)(休息日當(dāng)天時(shí)間為零處理)* @param startTimeYYYYMMDDHHMMSS 年月日時(shí)分秒* @param endTimeYYYYMMDDHHMMSS 年月日時(shí)分秒* @param lawHolidayList* @param lawWorkList* @return*/public static long workHours(Date startTimeYYYYMMDDHHMMSS,Date endTimeYYYYMMDDHHMMSS,List<Date> lawHolidayList,List<Date> lawWorkList) throws Exception {//開始時(shí)間轉(zhuǎn)成年月日格式SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");String strStartTimeYYYYMMDD = sdf.format(startTimeYYYYMMDDHHMMSS);Date startTimeYYYYMMDD = sdf.parse(strStartTimeYYYYMMDD);//開始時(shí)間是否屬于休息日boolean startTimeIsDayOff = isDayOff(startTimeYYYYMMDD, lawHolidayList, lawWorkList);//結(jié)束時(shí)間轉(zhuǎn)成年月日格式String strEndTimeYYYYMMDD = sdf.format(endTimeYYYYMMDDHHMMSS);Date endTimeYYYYMMDD = sdf.parse(strEndTimeYYYYMMDD);//結(jié)束時(shí)間是否屬于休息日boolean endTimeIsDayOff = isDayOff(endTimeYYYYMMDD, lawHolidayList, lawWorkList);//分為4種情況if (startTimeIsDayOff) {if (!endTimeIsDayOff) {//開始時(shí)間在休息日里,結(jié)束時(shí)間不在休息日里(開始那天不計(jì)算小時(shí)數(shù),結(jié)束那天計(jì)算小時(shí)數(shù))Calendar cal = Calendar.getInstance();cal.setTime(startTimeYYYYMMDD);cal.add(Calendar.DAY_OF_MONTH, +1);Date validStartTimeYYYYMMDD = cal.getTime();Date validStartTimeYYYYMMDDTemp = validStartTimeYYYYMMDD;int skipDay = 0;//循環(huán)遍歷開始時(shí)間之后的每一個(gè)日期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 {//開始時(shí)間在休息日里,結(jié)束時(shí)間也在休息日里(開始那天不計(jì)算小時(shí)數(shù),結(jié)束那天也不計(jì)算小時(shí)數(shù),看中間有多少個(gè)工作日)Calendar cal = Calendar.getInstance();cal.setTime(startTimeYYYYMMDD);cal.add(Calendar.DAY_OF_MONTH, +1);Date validStartTimeYYYYMMDD = cal.getTime();//工作日天數(shù)int workDays = 0;//循環(huán)遍歷開始時(shí)間之后的每一個(gè)日期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;//開始時(shí)間不在休息日里,結(jié)束時(shí)間在休息日里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 {//開始時(shí)間在不在休息日里,結(jié)束時(shí)間也不在休息日里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<Date> lawHolidayDate = new ArrayList<>();List<Date> 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("相差小時(shí)數(shù):"+workHours(startDate,endDate,lawHolidayDate,lawWorkDate));}上面的例子,需要在項(xiàng)目里配置兩種時(shí)間,一是國(guó)家法律規(guī)定的休息的時(shí)間,二是國(guó)家規(guī)定要正常上班的時(shí)間(例如一些周六日,為了十一的一天放假,調(diào)休前一個(gè)或者后一個(gè)周六日必須上班)。上面的例子是直接寫死的2018/2019年的兩種時(shí)間,自己項(xiàng)目的話,可以配置在配置文件或者數(shù)據(jù)庫中哦!
總結(jié)
以上是生活随笔為你收集整理的java 排除法定节假日以及正常周六日,计算两个Date相差的小时数的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: html新闻轮播插件,jQuery新闻类
- 下一篇: IxChariot 6.7 endpoi