首页 > 代码库 > 计算两个日期之间的工作日(去掉周末和节假日)
计算两个日期之间的工作日(去掉周末和节假日)
1 package com.utouu.uphone.commons; 2 3 import java.text.ParseException; 4 import java.text.SimpleDateFormat; 5 import java.util.ArrayList; 6 import java.util.Calendar; 7 import java.util.Date; 8 import java.util.Iterator; 9 import java.util.List; 10 11 import org.springframework.stereotype.Component; 12 /** 13 * 获取工作日 14 * <br>创建日期:2016年7月21日 15 * <br><b>Copyright 2016 UTOUU All Rights Reserved</b> 16 * @author zhushuangshuang 17 * @since 1.0 18 * @version 1.0 19 */ 20 @Component 21 public class GetWorkDay { 22 /** 23 * 获取两个时间之内的工作日时间(只去掉两个日期之间的周末时间,法定节假日未去掉) 24 * 25 * @param start 26 * -起始时间,共有3个重载方法,可以传入long型,Long型,与Date型 27 * @param end 28 * -结束时间,共有3个重载方法,可以传入long型,Long型,与Date型 29 * @return Long型时间差对象 30 */ 31 /*public static void main(String[] args) { 32 GetWorkDay g=new GetWorkDay(); 33 List<Date> initHoliday; 34 try { 35 initHoliday = g.initHoliday(); 36 double days = g.getWorkdayTimeInMillisExcWeekendHolidays("2016-06-30 17-12-53","2016-08-30 11-27-50","yyyy-MM-dd HH-mm-ss",initHoliday); 37 double formateToDay = g.formateToDay(days); 38 String formatDuring = g.formatDuring(days); 39 System.out.println(formateToDay); 40 System.out.println(formatDuring); 41 } catch (ParseException e) { 42 // TODO Auto-generated catch block 43 e.printStackTrace(); 44 } 45 } */ 46 47 private double getWorkdayTimeInMillis(long start, long end, 48 List<Date> listHolidays) { 49 50 // 如果起始时间大于结束时间,将二者交换 51 if (start > end) { 52 long temp = start; 53 start = end; 54 end = temp; 55 } 56 // 根据参数获取起始时间与结束时间的日历类型对象 57 Calendar sdate = Calendar.getInstance(); 58 Calendar edate = Calendar.getInstance(); 59 60 sdate.setTimeInMillis(start); 61 edate.setTimeInMillis(end); 62 63 // 计算指定时间段内法定节假日天数的毫秒数 64 long holidays = 0; 65 if (listHolidays != null) { 66 holidays = getHolidaysInMillis(start, end, listHolidays); 67 listHolidays.clear(); 68 } 69 70 // 如果两个时间在同一周并且都不是周末日期,则直接返回时间差,增加执行效率 71 if ((sdate.get(Calendar.YEAR) == edate.get(Calendar.YEAR)) 72 && (sdate.get(Calendar.WEEK_OF_YEAR) == edate 73 .get(Calendar.WEEK_OF_YEAR)) 74 && (sdate.get(Calendar.DAY_OF_WEEK) != 1 && sdate 75 .get(Calendar.DAY_OF_WEEK) != 7) 76 && (edate.get(Calendar.DAY_OF_WEEK) != 1 && edate 77 .get(Calendar.DAY_OF_WEEK) != 7)) { 78 return new Long(end - start - holidays); 79 } 80 // 如果两个时间在同一周并且都是周末日期,则直接返回0 81 if ((sdate.get(Calendar.YEAR) == edate.get(Calendar.YEAR)) 82 && (sdate.get(Calendar.WEEK_OF_YEAR) == edate 83 .get(Calendar.WEEK_OF_YEAR)-1) 84 && (sdate.get(Calendar.DAY_OF_WEEK) == 1 85 || sdate.get(Calendar.DAY_OF_WEEK) == 7) 86 && 87 (edate.get(Calendar.DAY_OF_WEEK) == 1 88 || edate.get(Calendar.DAY_OF_WEEK) == 7)) { 89 start=validateStartTime(sdate); 90 end=validateEndTime(edate); 91 long result=end - start - holidays; 92 return new Long(result>0?result:0); 93 } 94 95 start=validateStartTime(sdate); 96 end=validateEndTime(edate); 97 98 // 首先取得起始日期与结束日期的下个周一的日期 99 Calendar snextM = getNextMonday(sdate);100 Calendar enextM = getNextMonday(edate);101 102 // 获取这两个周一之间的实际天数103 int days = getDaysBetween(snextM, enextM);104 105 // 获取这两个周一之间的工作日数(两个周一之间的天数肯定能被7整除,并且工作日数量占其中的5/7)106 int workdays = days / 7 * 5;107 108 // 计算最终结果,具体为:workdays加上开始时间的时间偏移量,减去结束时间的时间偏移量109 double a=(double)workdays*24*3600000;110 double result = (a + calcWorkdayTimeInMillis(sdate, edate, start, end) - holidays);111 return result > 0 ? result : 0;112 }113 /***114 * 验证开始日期是否合法,如果不合法,并返回修复后的正确日期毫秒数115 * @param sdate116 * @return117 */118 private long validateStartTime(Calendar sdate){119 if(sdate.get(Calendar.DAY_OF_WEEK) == 1)//开始日期从周日开始,如果开始时间为周末,自动修复为下周的9:00开始120 {121 sdate.add(Calendar.DATE,1);122 sdate.setTimeInMillis(sdate.getTime().getTime()- //从9点开始123 (((sdate.get(Calendar.HOUR_OF_DAY)-9) * 3600000)+ (sdate.get(Calendar.MINUTE) * 60000)+ (sdate.get(Calendar.SECOND) * 1000)));124 }else if(sdate.get(Calendar.DAY_OF_WEEK) == 7){//开始日期从周六开始125 sdate.add(Calendar.DATE,2);126 sdate.setTimeInMillis(127 sdate.getTime().getTime()- //从9点开始,如果开始时间为周末,自动修复为下周的9:00开始128 (((sdate.get(Calendar.HOUR_OF_DAY)-9) * 3600000)129 + (sdate.get(Calendar.MINUTE) * 60000)130 + (sdate.get(Calendar.SECOND) * 1000)));131 }132 return sdate.getTimeInMillis();133 }134 135 136 /***137 * 验证结束日期是否合法,如果不合法,并返回修复后的正确日期毫秒数138 * @param sdate139 * @return140 */141 private long validateEndTime(Calendar edate)142 {143 if(edate.get(Calendar.DAY_OF_WEEK) == 1)//结束日期是周日,如果结束日期是周六、周末自动修复为这周五18:00144 {145 edate.add(Calendar.DATE,-2);146 edate.setTimeInMillis(147 edate.getTime().getTime()+148 (18*3600000-((edate.get(Calendar.HOUR_OF_DAY) * 3600000)149 + (edate.get(Calendar.MINUTE) * 60000)150 + (edate.get(Calendar.SECOND) * 1000))));151 }else if(edate.get(Calendar.DAY_OF_WEEK) == 7){//结束日期是周六,如果结束日期是周六、周末自动修复为这周五18:00152 edate.add(Calendar.DATE,-1);153 edate.setTimeInMillis(154 edate.getTime().getTime()+155 (18*3600000-((edate.get(Calendar.HOUR_OF_DAY) * 3600000)156 + (edate.get(Calendar.MINUTE) * 60000)157 + (edate.get(Calendar.SECOND) * 1000))));}158 return edate.getTimeInMillis();159 }160 /***161 * 计算两个日期间的工作日天数,除周六日162 *163 * @param sdate164 * @param edate165 * @return166 */167 private long calcWorkdayTimeInMillis(Calendar sdate, Calendar edate,long start, long end) {168 // 获取开始时间的偏移量169 long scharge = 0;170 if (sdate.get(Calendar.DAY_OF_WEEK) != 1171 && sdate.get(Calendar.DAY_OF_WEEK) != 7) {172 // 只有在开始时间为非周末的时候才计算偏移量173 scharge += (sdate.get(Calendar.HOUR_OF_DAY) * 3600000);174 scharge += (sdate.get(Calendar.MINUTE) * 60000);175 scharge += (sdate.get(Calendar.SECOND) * 1000);176 scharge = ((24 * 3600000) - scharge);177 178 scharge += ((sdate.getTime().getTime() - start) - (3 * 24 * 3600000));179 }180 // (24*3600000=86400000)-((9*3600000+1800000)=34200000)+(3*24*3600000=259200000)-(2*24*3600000)=181 // 86400000-34200000=52200000182 // 获取结束时间的偏移量183 long echarge = 0;184 if (edate.get(Calendar.DAY_OF_WEEK) != 1185 && edate.get(Calendar.DAY_OF_WEEK) != (7)) {186 // 只有在结束时间为非周末的时候才计算偏移量187 echarge += (edate.get(Calendar.HOUR_OF_DAY) * 3600000);188 echarge += (edate.get(Calendar.MINUTE) * 60000);189 echarge += (edate.get(Calendar.SECOND) * 1000);190 echarge = ((24 * 3600000) - echarge);191 echarge += (edate.getTime().getTime() - end) - (24 * 3600000);192 echarge -= (2 * 24 * 3600000);193 }194 // (24*3600000=86400000)-(18*3600000=64800000)+(24*3=259200000)195 if (scharge < 0 || echarge < 0)196 scharge = echarge = 0;197 return scharge - echarge;198 }199 200 /**201 * 获取两个时间之内的工作日时间(只去掉两个日期之间的周末时间,法定节假日未去掉)202 *203 * @param start204 * -起始时间,共有3个重载方法,可以传入long型,Long型,与Date型205 * @param end206 * -结束时间,共有3个重载方法,可以传入long型,Long型,与Date型207 * @return Long型时间差对象208 */209 public double getWorkdayTimeInMillisExcWeekend(long start, long end) {210 return getWorkdayTimeInMillis(start, end);211 }212 213 /***214 * 获取两个时间之内的工作日时间(去掉两个日期之间的周末时间,法定节假日时间)215 *216 * @param start217 * @param end218 * @return219 */220 public double getWorkdayTimeInMillisExcWeekendHolidays(String start,String end, String format, List<Date> listHolidays) {221 SimpleDateFormat sdf = new SimpleDateFormat(format);222 Date sdate;223 Date edate;224 try {225 sdate = sdf.parse(start);226 edate = sdf.parse(end);227 return getWorkdayTimeInMillis(sdate.getTime(), edate.getTime(),228 listHolidays);229 } catch (ParseException e) {230 e.printStackTrace();231 return new Long(0);232 }233 }234 235 public double getWorkdayTimeInMillis(Long start, Long end) {236 return getWorkdayTimeInMillis(start.longValue(), end.longValue(), null);237 }238 239 public double getWorkdayTimeInMillis(Date start, Date end) {240 return getWorkdayTimeInMillis(start.getTime(), end.getTime(), null);241 }242 243 public double getWorkdayTimeInMillis(String start, String end, String format) {244 SimpleDateFormat sdf = new SimpleDateFormat(format);245 Date sdate;246 Date edate;247 try {248 sdate = sdf.parse(start);249 edate = sdf.parse(end);250 return getWorkdayTimeInMillis(sdate, edate);251 } catch (ParseException e) {252 e.printStackTrace();253 return new Long(0);254 }255 }256 257 private long getHolidaysInMillis(long start, long end,258 List<Date> listHolidays) {259 Calendar scalendar = Calendar.getInstance();260 Calendar ecalendar = Calendar.getInstance();261 int daysofH = 0;262 try {263 264 scalendar.setTimeInMillis(start);265 ecalendar.setTimeInMillis(end);266 267 if (listHolidays == null)268 return new Long(0);269 Iterator<Date> iterator = listHolidays.iterator();270 while (iterator.hasNext()) {271 Calendar ca = Calendar.getInstance();272 Date hdate = iterator.next();273 ca.setTime(hdate);274 if (ca.after(scalendar) && ca.before(ecalendar)) {275 daysofH = daysofH + 1;276 } else if (ca.getTimeInMillis() == scalendar.getTimeInMillis()) {277 daysofH = daysofH + 1;278 } else if (ca.getTimeInMillis() == ecalendar.getTimeInMillis()) {279 daysofH = daysofH + 1;280 }281 }282 283 } catch (Exception e) {284 e.printStackTrace();285 return new Long(0);286 }287 return daysofH * 24 * 3600000;288 }289 290 291 private Calendar getNextMonday(Calendar cal) {292 int addnum = 9 - cal.get(Calendar.DAY_OF_WEEK);293 if (addnum == 8)294 addnum = 1;// 周日的情况295 cal.add(Calendar.DATE, addnum);296 return cal;297 }298 299 /**300 *301 * @param mss 302 * @param 要转换的毫秒数303 * @return 该毫秒数转换为 * days * hours * minutes * seconds 后的格式304 */305 public String formatDuring(double mss) {306 long days = (long) (mss / (1000 * 60 * 60 * 24));307 long hours = (long) ((mss % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));308 long minutes = (long) ((mss % (1000 * 60 * 60)) / (1000 * 60));309 long seconds = (long) ((mss % (1000 * 60)) / 1000);310 return days + " days " + hours + " hours " + minutes + " minutes "311 + seconds + " seconds ";312 }313 314 /**315 * 获取两个日期之间的实际天数,支持跨年316 * @param start 317 * @param end 318 * 319 */320 /**321 * 获得两个日期之间的工作日322 * @since 1.0 323 * @param mss324 * @return325 * <br><b>作者: @author zhushunagshuang</b>326 * <br>创建时间:2016年7月21日 下午3:12:23327 */328 public double formateToDay(double mss){329 double days = mss / (1000 * 60 * 60 * 24);330 return days;331 }332 333 public int getDaysBetween(Calendar start, Calendar end) {334 if (start.after(end)) {335 Calendar swap = start;336 start = end;337 end = swap;338 }339 340 int days = end.get(Calendar.DAY_OF_YEAR)- start.get(Calendar.DAY_OF_YEAR);341 int y2 = end.get(Calendar.YEAR);342 if (start.get(Calendar.YEAR) != y2) {343 start = (Calendar) start.clone();344 do {345 days += start.getActualMaximum(Calendar.DAY_OF_YEAR);346 start.add(Calendar.YEAR, 1);347 } while (start.get(Calendar.YEAR) != y2);348 349 }350 return days;351 }352 /**353 * 手动维护2016年的节假日354 * @since 1.0 355 * @return356 * @throws ParseException357 * <br><b>作者: @author zhushunagshuang</b>358 * <br>创建时间:2016年7月21日 下午5:12:08359 */360 public List<Date> initHoliday() throws ParseException{ 361 List<Date> holidays = new ArrayList<Date>();362 SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");363 //元旦364 holidays.add(sdf.parse("2016-01-01"));365 holidays.add(sdf.parse("2016-01-02"));366 holidays.add(sdf.parse("2016-01-03"));367 //春节368 holidays.add(sdf.parse("2016-02-07"));369 holidays.add(sdf.parse("2016-02-08"));370 holidays.add(sdf.parse("2016-02-09"));371 holidays.add(sdf.parse("2016-02-10"));372 holidays.add(sdf.parse("2016-02-11"));373 holidays.add(sdf.parse("2016-02-12"));374 holidays.add(sdf.parse("2016-02-13"));375 //清明节376 holidays.add(sdf.parse("2016-04-02"));377 holidays.add(sdf.parse("2016-04-03"));378 holidays.add(sdf.parse("2016-04-04"));379 //劳动节380 holidays.add(sdf.parse("2016-04-30"));381 holidays.add(sdf.parse("2016-05-01"));382 holidays.add(sdf.parse("2016-05-02"));383 //端午节384 holidays.add(sdf.parse("2016-06-09"));385 holidays.add(sdf.parse("2016-06-10"));386 holidays.add(sdf.parse("2016-06-11"));387 //中秋节388 holidays.add(sdf.parse("2016-09-15"));389 holidays.add(sdf.parse("2016-09-16"));390 holidays.add(sdf.parse("2016-09-17"));391 //国庆节392 holidays.add(sdf.parse("2016-10-01"));393 holidays.add(sdf.parse("2016-10-02"));394 holidays.add(sdf.parse("2016-10-03"));395 holidays.add(sdf.parse("2016-10-04"));396 holidays.add(sdf.parse("2016-10-05"));397 holidays.add(sdf.parse("2016-10-06"));398 holidays.add(sdf.parse("2016-10-07"));399 return holidays;400 }401 402 }403
计算两个日期之间的工作日(去掉周末和节假日)
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。