java 工作日日期計算
阿新 • • 發佈:2018-12-14
public class DateUtil { private static SimpleDateFormat hm = new SimpleDateFormat("HH:mm"); private static SimpleDateFormat ymd = new SimpleDateFormat("yyyy-MM-dd"); private static SimpleDateFormat ymdhm = new SimpleDateFormat("yyyy-MM-dd HH:mm"); private static Date lunchBreak = null; private static Date workGoOn = null; private static Date offDuty = null; private static Date startWork = null; static { try { lunchBreak = hm.parse("12:30"); workGoOn = hm.parse("14:00"); offDuty = hm.parse("18:30"); startWork = hm.parse("09:30"); } catch (ParseException e) { e.printStackTrace(); } } /** * 工作日內時間加法計算 * @param date * @return */ public static Date addInWorkDate(Date date,int hour) throws ParseException { // hour = hour * 14; //將要加的時間計算出來,需要加幾天,每天按照7.5小時計算,超過整數天當成多一天計算 //先計算天數,如果添加了之後在週末,需要多加兩天 //最後計算小時和分鐘是否在工作時段,如果不在,順延 //注意,雖然天數已經計算了,超過了也多加了一天,但是如果在哪一天最後的工作時段,多加了一個小時,還是會跨天:解決方法,將計算的時間加上天數剩餘的小時,檢視是否超過了最後的工作時間,如果超過了,再多加一天 Double oneDay = 7.5; Double days = hour / oneDay; Double littleNum = Double.valueOf("0."+days.toString().split("\\.")[1]); int intDay = days.intValue(); Double remainHour = littleNum * oneDay; //剩餘的小時數轉換為分,通過日曆計算是否超過了最後的下班時間,如果超過了,天數加1,小時和天分開算 Integer millSeconds = new Double(remainHour * 60 * 60 * 1000).intValue(); Date jumpRestday = jumpRestday(date, intDay,millSeconds); Date jumpRestTime = jumpRestTime(date, millSeconds); Date ret = ymdhm.parse(ymd.format(jumpRestday) + " " + hm.format(jumpRestTime)); return ret; } private static String checkAndFixHm(String time) throws ParseException { Date parse = hm.parse(time); if (parse.before(startWork)) { parse = startWork; }else if(parse.after(lunchBreak) && parse.before(workGoOn)){ parse = workGoOn; }else if(parse.after(offDuty)){ parse = startWork; } return hm.format(parse); } /** * 計算時間 * 時間校驗 * @param date * @param millSeconds * @return */ private static Date jumpRestTime(Date date,Integer millSeconds) throws ParseException { String dateStr = checkAndFixHm(hm.format(date)); date = hm.parse(dateStr); Calendar calendar = Calendar.getInstance(); calendar.setTime(date); /** * 當前邏輯是:指定時間在中午以前,直接加,加完判斷是否超過了午休時間,如果超過了,在下午上班時間的基礎上增加差量 * * 如果當前時間在下班以後,計算當前時間 * * * 正確的邏輯是:當前時間如果在中午下班之前,直接加,加完檢查是否超過了午休,如果是,計算差量,將差量加到下午上班以後 * * 如果指定時間在下午上班之後,直接加,加完檢查是否超過了晚上下班,如果超過了,將差量加到第二天早上上班 * */ //判斷是否跨越了中午,指定的時間如果是在上午,加上時間量超過了午休時間就是跨越了中午,需要把多的時間加到下午去 if (calendar.getTime().before(lunchBreak) || calendar.getTime().equals(lunchBreak)) { calendar.add(Calendar.MILLISECOND,millSeconds); Date temp = calendar.getTime(); if (temp.after(lunchBreak)) { Long dif = temp.getTime() - lunchBreak.getTime(); calendar.setTime(workGoOn); calendar.add(Calendar.MILLISECOND,dif.intValue()); temp = calendar.getTime(); return temp; } }else if(calendar.getTime().after(workGoOn) || calendar.getTime().equals(workGoOn)){ //判斷是否跨越了晚上,指定的時間如果超過了下班時間,需要把多餘的時間從早上加 calendar.add(Calendar.MILLISECOND,millSeconds); Date temp = calendar.getTime(); if (temp.after(offDuty)) { Long dif = temp.getTime() - offDuty.getTime(); calendar.setTime(startWork); calendar.add(Calendar.MILLISECOND,dif.intValue()); temp = calendar.getTime(); return temp; } } Date time = calendar.getTime(); return time; } /** * 判斷時間是否超過了最晚下班時間,如果是,新增一天 * @return */ private static int judgeIsAddOneDay(Date date,Integer millSeconds) throws ParseException { String dateStr = checkAndFixHm(hm.format(date)); date = hm.parse(dateStr); Calendar calendar = Calendar.getInstance(); calendar.setTime(date); //判斷是否跨越了中午,指定的時間如果是在上午,加上時間量超過了午休時間就是跨越了中午,需要把多的時間加到下午去 if(calendar.getTime().after(workGoOn) || calendar.getTime().equals(workGoOn)){ //判斷是否跨越了晚上,指定的時間如果超過了下班時間,需要把多餘的時間從早上加 calendar.add(Calendar.MILLISECOND,millSeconds); Date temp = calendar.getTime(); if (temp.after(offDuty)) { return 1; } } return 0; } private static Date jumpRestday(Date timeVar,int amount,Integer millSeconds) throws ParseException { Calendar calendar = Calendar.getInstance(); calendar.setTime(timeVar); //判斷時間是否過了當天工作時間,如果過了,新增一天 int i1 = judgeIsAddOneDay(timeVar, millSeconds); if (i1 == 1) { } amount = amount + i1; if (hm.parse(hm.format(timeVar)).after(offDuty)) { calendar.add(Calendar.DATE,1); timeVar = calendar.getTime(); } int i = amount / 5; int dif = amount - (i * 5); // System.out.println(i+"倍"+(dif > 0 ? "餘"+dif : "")); int ac = amount; if (i != 0) { ac = amount + (i * 2); } //判斷餘數加上當前時間是否跨越了週末,如果是,再加兩天 // 星期六:7,星期天:1 Calendar instance = Calendar.getInstance(); instance.clear(); instance.setTime(timeVar); int weekInt = instance.get(Calendar.DAY_OF_WEEK); if(weekInt + dif > 6 || weekInt + dif == 1){ calendar.add(Calendar.DATE,2); } calendar.add(Calendar.DATE,ac); //如果遇到週末,直接加兩天 if (Calendar.SATURDAY == calendar.get(Calendar.DAY_OF_WEEK)) { calendar.add(Calendar.DATE,2); }else if(Calendar.SUNDAY == calendar.get(Calendar.DAY_OF_WEEK)){ calendar.add(Calendar.DATE,2); } Date time = calendar.getTime(); return time; } public static String formatYmdhm(Date date){ String format = ymdhm.format(date); return format; } }
測試
@Test
public void testDate() throws ParseException {
Date date = ymdhm.parse("2018-07-20 20:14");
Date ret = DateUtil.addInWorkDate(date, 8);
System.out.println(ret.toLocaleString());
}
結果
2018-7-24 10:00:00