1. 程式人生 > >java 工作日,工作時間內的時間增量計算

java 工作日,工作時間內的時間增量計算

/**
 * @author xiaogang
 * @date 2018/7/19 18:01
 */
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