1. 程式人生 > >時效演算法-給定開始時間和環節時效計算結束時間,考慮節假日、調休日和正常雙休

時效演算法-給定開始時間和環節時效計算結束時間,考慮節假日、調休日和正常雙休

感謝原博主的博文 https://blog.csdn.net/zjnxyz/article/details/17164369

我是在原博主的基礎上優化了下,增加了法定節假日和調休日的手動維護工具類,在此記錄一下,以便以後碰到類似問題。

維護工具類

/**
 * 手動維護法定節假日和法定調休日工具類
 * @author MaJian
 *
 */
public class InsertHolidayUtil {
 
    public static void main(String[] args){
        //驅動程式名
        String driver = "com.mysql.jdbc.Driver";
       // String driver = "oracle.jdbc.driver.OracleDriver";
        //要插入的資料庫
        String url = "你的資料庫連線地址";
        //String url = "jdbc:oracle:thin:@127.0.0.1:1521:orcl";
        String user = "使用者名稱";
        String password = "密碼";
        DriverManagerDataSource ds = new DriverManagerDataSource();       
        try {
            ds.setDriverClassName(driver);       
            ds.setUrl(url);       
            ds.setUsername(user);       
            ds.setPassword(password);
            Connection actualCon = ds.getConnection(); 
            Statement statement = actualCon.createStatement();
 
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            Date start = sdf.parse("2019-02-05");//開始時間
            Date end = sdf.parse("2020-12-31");//結束時間
            //List<Date> lists = dateSplit(start, end);
            List<Date> lists = new ArrayList<Date>();
            List<Date> holidays = getHolidays();
            List<Date> workDays = getWorkDays();
            //手動插入一個時間段的所有時間
            if (!lists.isEmpty()) {
                for (Date date : lists) {
                    Calendar cal = Calendar.getInstance();
                    cal.setTime(date);
                    System.out.println("********插入日期:" + sdf.format(date) + "***********");
                    int week = cal.get(Calendar.DAY_OF_WEEK)-1;
                    String weekStr = "";
                    if(week == 0){
                        weekStr = "星期日";
                    }
                    if(week == 1){
                        weekStr = "星期一";
                    }
                    if(week == 2){
                        weekStr = "星期二";                  
                    }
                    if(week == 3){
                        weekStr = "星期三";
                    }
                    if(week == 4){
                        weekStr = "星期四";
                    }
                    if(week == 5){
                        weekStr = "星期五";
                    }
                    if(week == 6){
                        weekStr = "星期六";
                    }
                    String insertSql = "INSERT INTO mc_holiday (DAYLIST, WEEKLIST, IS_HOLIDAY, INCREMENT) " +
                            "VALUES('"+sdf.format(date)+"','"+weekStr+"','"+isHoliday(date)+"','')";
                    statement.execute(insertSql);
                }
            }
            //法定調休日
            if (!workDays.isEmpty()) {
                for (Date date : workDays) {
                    Calendar cal = Calendar.getInstance();
                    cal.setTime(date);
                    System.out.println("********插入日期:" + sdf.format(date) + "***********");
                    int week = cal.get(Calendar.DAY_OF_WEEK)-1;
                    String weekStr = "";
                    if(week == 0){
                        weekStr = "星期日";
                    }
                    if(week == 1){
                        weekStr = "星期一";
                    }
                    if(week == 2){
                        weekStr = "星期二";                  
                    }
                    if(week == 3){
                        weekStr = "星期三";
                    }
                    if(week == 4){
                        weekStr = "星期四";
                    }
                    if(week == 5){
                        weekStr = "星期五";
                    }
                    if(week == 6){
                        weekStr = "星期六";
                    }
                    String insertSql = "INSERT INTO mc_holiday (DAYLIST, WEEKLIST, IS_HOLIDAY, INCREMENT) " +
                            "VALUES('"+sdf.format(date)+"','"+weekStr+"','0','"+sdf.format(date).substring(0,4)+"')";
                    statement.execute(insertSql);
                }
            }
            //法定節假日
            if (!holidays.isEmpty()) {
                for (Date date : holidays) {
                    Calendar cal = Calendar.getInstance();
                    cal.setTime(date);
                    System.out.println("********插入日期:" + sdf.format(date) + "***********");
                    int week = cal.get(Calendar.DAY_OF_WEEK)-1;
                    String weekStr = "";
                    if(week == 0){
                        weekStr = "星期日";
                    }
                    if(week == 1){
                        weekStr = "星期一";
                    }
                    if(week == 2){
                        weekStr = "星期二";                  
                    }
                    if(week == 3){
                        weekStr = "星期三";
                    }
                    if(week == 4){
                        weekStr = "星期四";
                    }
                    if(week == 5){
                        weekStr = "星期五";
                    }
                    if(week == 6){
                        weekStr = "星期六";
                    }
                    String insertSql = "INSERT INTO mc_holiday (DAYLIST, WEEKLIST, IS_HOLIDAY, INCREMENT) " +
                             "VALUES('"+sdf.format(date)+"','"+weekStr+"','1','"+sdf.format(date).substring(0,4)+"')";
                    statement.execute(insertSql);
                }
            }
            actualCon.close();
        }catch(Exception e) {
            e.printStackTrace();
        }
    }
    /**
     * 法定節假日
     * @return
     */
    private static List<Date> getHolidays(){
        List<Date> holidays = new ArrayList<Date>();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        try {
            //元旦
            holidays.add(sdf.parse("2018-01-01"));
            //春節
            holidays.add(sdf.parse("2018-02-15"));
            holidays.add(sdf.parse("2018-02-16"));
            holidays.add(sdf.parse("2018-02-17"));
            holidays.add(sdf.parse("2018-02-18"));
            holidays.add(sdf.parse("2018-02-19"));
            holidays.add(sdf.parse("2018-02-20"));
            holidays.add(sdf.parse("2018-02-21"));
            //清明
            holidays.add(sdf.parse("2018-04-05"));
            holidays.add(sdf.parse("2018-04-06"));
            holidays.add(sdf.parse("2018-04-07"));
            //勞動節
            holidays.add(sdf.parse("2018-04-29"));
            holidays.add(sdf.parse("2018-04-30"));
            holidays.add(sdf.parse("2018-05-01"));
            //端午節
            holidays.add(sdf.parse("2018-06-16"));
            holidays.add(sdf.parse("2018-06-17"));
            holidays.add(sdf.parse("2018-06-18"));
            //中秋節
            holidays.add(sdf.parse("2018-09-22"));
            holidays.add(sdf.parse("2018-09-23"));
            holidays.add(sdf.parse("2018-09-24"));
            //國慶節
            holidays.add(sdf.parse("2018-10-01"));
            holidays.add(sdf.parse("2018-10-02"));
            holidays.add(sdf.parse("2018-10-03"));
            holidays.add(sdf.parse("2018-10-04"));
            holidays.add(sdf.parse("2018-10-05"));
            holidays.add(sdf.parse("2018-10-06"));
            holidays.add(sdf.parse("2018-10-07"));
        } catch (Exception e) {
            e.printStackTrace();
        }
        return holidays;
    }
    /**
     * 法定調休日
     * @return
     */
    private static List<Date> getWorkDays(){
        List<Date> workDays = new ArrayList<Date>();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        try {
            //春節
            workDays.add(sdf.parse("2018-02-11"));
            workDays.add(sdf.parse("2018-02-24"));
            //清明
            workDays.add(sdf.parse("2018-04-08"));
            //勞動節
            workDays.add(sdf.parse("2018-04-28"));
            //國慶節
            workDays.add(sdf.parse("2018-09-29"));
            workDays.add(sdf.parse("2018-09-30"));
        } catch (Exception e) {
            e.printStackTrace();
        }
        return workDays;
    }
    
    private static List<Date> dateSplit(Date start, Date end) throws Exception {
        if (!start.before(end))
            throw new Exception("開始時間應該在結束時間之後");
        Long spi = end.getTime() - start.getTime();
        int step = (int) (spi / (24 * 60 * 60 * 1000));// 相隔天數
        List<Date> dateList = new ArrayList<Date>();
        dateList.add(start);
        for (int i = 0; i < step; i++) {
            dateList.add(new Date(dateList.get(i).getTime() + (24 * 60 * 60 * 1000)));// 比上一天減一
        }
        return dateList;
    }
 
    /**
     * 判斷是否為節假日,若是返回1,否則返回0
     * @param date
     * @return
     */
    private static int isHoliday(Date date){
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        List<Date> holidays = getHolidays();
        List<Date> workdays = getWorkDays();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
//        System.out.println(sdf.format(date));
        if(((cal.get(Calendar.DAY_OF_WEEK)==Calendar.SATURDAY||cal.get(Calendar.DAY_OF_WEEK)==Calendar.SUNDAY)&&!workdays.contains(sdf.format(date))) || holidays.contains(sdf.format(date)) ) {
            return 1;
        }
        return 0;
    }
 
    private static Date getLastWorkDay(Date date){
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.add(Calendar.DAY_OF_MONTH,-1);
        Date dateTemp = cal.getTime();
 
        while (isHoliday(dateTemp) != 0){
            cal.add(Calendar.DAY_OF_MONTH,-1);
            dateTemp = cal.getTime();
        }
        return dateTemp;
    }

下面是時限計算和時間段相差的邏輯程式碼,工作時間可以從資料庫或配置檔案取,這樣可以更靈活

public class DateCal {

    //工作時間
    private String morningBegin = "08:30";//上午開始時間
    private String morningEnd = "12:00";//上午結束時間
    private String afternoonBegin = "14:00";//下午開始時間
    private String afternoonEnd  = "18:00";//結束時間
    /**
     * 根據日期計算xx小時後對應日期,刨除工作日、節假日
     *
     * @param d
     * @param hours
     * @return
     */
    public Date getPluseHourDate(Date d, double hours){
        Calendar cal_start = Calendar.getInstance();
        cal_start.setTime(d);
        return func(cal_start, hours);
    }
    /**
     * 計算兩個日期之間的時間差,不算節假日、不算週末、不算非正常工作時間
     * <p>
     * 設計思路:
     * 取開始時間,判斷是否是節假日、是否是週末、是否是加班日
     * 如果是節假日:
     * 往後+1天,再繼續判斷
     * 如果是週末:
     * 判斷是否是加班日,如果不是加班日,往後+1天
     *
     * @param begin 開始時間
     * @param end   結束時間
     * @return 時間差,單位是毫秒
     */
    public long getMinusofTowDate(Calendar begin, Calendar end){
        long midL = 0;//中間差值時間
        // 0.預處理
        begin = getBeginDay(begin);
        end = getEndDay(end);
        // 1.如果開始時間大於結束時間,交換下,同時結果返回負數即可
        if (begin.after(end)){
            Calendar swap = begin;
            begin = end;
            end = swap;
            midL = -getDayMiLLI(begin, end);
        }else{
            midL = getDayMiLLI(begin, end);
        }
        // 2.計算開始
        return midL;
    }
    /**
     * 判斷是否是法定節假日
     * 關於法定節假日,這裡還有一個問題需要提前考慮下
     * 例如:
     * 國慶10月1號到10月7號,那10月8號正式上班,但是如果10月8號是週日,在計算的時候,也會不考慮進去。這就比較尷尬。
     * 另外就是10月8號是不是週末,不同年份又不同。
     * 處理辦法:
     * 把可能產生上述問題的日期,都單獨拎出來,在計算的時候,先判斷是否滿足這些日期,再判斷這些日期是否是週末
     * 如果不是週末,正常計算,如果是週末,還要加上當天的時間。
     * @param d1
     * @return
     */
    private boolean isHodliDays(Calendar d1){
	    //法定節假日,當然這個地方是從資料庫裡取出來的
        private String isHoliday = "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";
    	SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
    	String time = format.format(d1.getTime());
        //String str = String.valueOf(d1.get(Calendar.MONTH) + 1) + "-" + String.valueOf(d1.get(Calendar.DAY_OF_MONTH));
        if (isHoliday.contains(time)){
            return true;
        }
        return false;
    }

    //判斷是否是加班日
    private boolean isPlusDay(Calendar d1){
        //節假日前後的加班,當然這個地方是從資料庫裡取出來的
        private String isPlusDau = "2018-09-29,2018-09-30";
    	SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
    	String time = format.format(d1.getTime());
        //String str = String.valueOf(d1.get(Calendar.MONTH) + 1) + "-" + String.valueOf(d1.get(Calendar.DAY_OF_MONTH));
        if (isPlusDau.contains(time)){
            return true;
        }
        return false;
    }

    //判斷是否是週末
    private boolean isWeek(Calendar d1){
        if (d1.get(Calendar.DAY_OF_WEEK) == Calendar.SATURDAY || d1.get(Calendar.DAY_OF_WEEK) == Calendar.SUNDAY){
            return true;
        }
        return false;
    }

    //預處理開始時間
    private Calendar getBeginDay(Calendar d1){
        if (isHodliDays(d1)){
            //如果是節假日,往後延一天,並且從這一天的00:00:00開始
            d1 = addCalendar(d1, 1);
            return getBeginDay(d1);
        }else{
            //再判斷是否是週末,如果是週末,判斷是否是加班日
            if (isWeek(d1)){
                if (!isPlusDay(d1)){
                    d1 = addCalendar(d1, 1);
                    return getBeginDay(d1);
                }else{
                    return d1;
                }
            }
            else{
                return d1;
            }
        }
    }

    //預處理結束時間
    private Calendar getEndDay(Calendar d2){
        if (isHodliDays(d2)){
            //如果是節假日,往前提一天,並且從這一天的00:00:00開始
            d2 = addCalendar(d2, -1);
            return getEndDay(d2);
        }else{
            //不是節假日
            if (isWeek(d2)){
                if (!isPlusDay(d2)){
                    d2 = addCalendar(d2, -1);
                    return getEndDay(d2);
                }else{
                    return d2;
                }
            }
            else{
                return d2;
            }
        }
    }

    //預處理重置時分秒
    private Calendar addCalendar(Calendar d, int m){
        if (m == 1){
            d.add(Calendar.DATE, 1);
            d.set(Calendar.HOUR_OF_DAY, 0);//也可直接設定為beginHour
            d.set(Calendar.MINUTE, 0);
            d.set(Calendar.SECOND, 0);
        }else{
            d.add(Calendar.DATE, -1);
            d.set(Calendar.HOUR_OF_DAY, 23);//也可直接設定為endHour
            d.set(Calendar.MINUTE, 59);
            d.set(Calendar.SECOND, 59);
        }
        return d;
    }
   /* private boolean compareTimes(String time1,String time2){
    	try {
    		SimpleDateFormat sdf=new SimpleDateFormat("hh:mm");
    		//將字串形式的時間轉化為Date型別的時間
    		Date a=sdf.parse(time1);
    		Date b=sdf.parse(time2);
        	if(a.before(b)){
        		return true;
        	}else{
        		return false;
        	}
		} catch (Exception e) {
			e.printStackTrace();
		}
    	return true;
    }*/
    //獲取當天實際的工作時間
    private long getDayMiLLI(Calendar d, boolean isBegin){
        long rv = 0;
        int  h = d.get(Calendar.HOUR_OF_DAY);
        SimpleDateFormat format = new SimpleDateFormat("HH:mm");
    	String time = format.format(d.getTime());
    	try {
			Date hTime = format.parse(time);
			Date mgBegin = format.parse(morningBegin);
			Date mgEnd = format.parse(morningEnd);
			Date afBegin = format.parse(afternoonBegin);
			Date afend = format.parse(afternoonEnd);
	        if (isBegin){
	            if (hTime.getTime() < afend.getTime()){
	                if (hTime.getTime() >= mgBegin.getTime()){
	                    if (hTime.getTime() >= afBegin.getTime()){
	                        //計算開始那一天的時間長度
	                        rv += afend.getTime() - hTime.getTime();
	                       // rv -= d.get(Calendar.MINUTE) * 60 * 1000;
	                        rv -= d.get(Calendar.SECOND) * 1000;
	                        rv -= d.get(Calendar.MILLISECOND);
	                    }else if (hTime.getTime() >= mgEnd.getTime() && hTime.getTime() < afBegin.getTime()){
	                        rv += afend.getTime() - afBegin.getTime();
	                    }else{
	                        rv += (afend.getTime() - afBegin.getTime()) + (mgEnd.getTime() - hTime.getTime());
	                        //rv -= d.get(Calendar.MINUTE) * 60 * 1000;
	                        rv -= d.get(Calendar.SECOND) * 1000;
	                        rv -= d.get(Calendar.MILLISECOND);
	                    }
	                }else{
	                    rv = (afend.getTime() - afBegin.getTime()) + (mgEnd.getTime() - mgBegin.getTime());
	                }
	            }
	        }else{
	            if (hTime.getTime() >= mgBegin.getTime()){
	                if (hTime.getTime() < afend.getTime()){
	                    if (hTime.getTime() >= afBegin.getTime()){
	                        rv += (mgEnd.getTime() - mgBegin.getTime()) + (hTime.getTime() - afBegin.getTime());
	                        //rv += d.get(Calendar.MINUTE) * 60 * 1000;
	                        rv += d.get(Calendar.SECOND) * 1000;
	                        rv += d.get(Calendar.MILLISECOND);
	                    }else if (hTime.getTime() >= mgEnd.getTime() && hTime.getTime() < afBegin.getTime()){
	                        rv += mgEnd.getTime() - mgBegin.getTime();
	                    }else{
	                        rv += hTime.getTime() - mgBegin.getTime();
	                        //rv += d.get(Calendar.MINUTE) * 60 * 1000;
	                        rv += d.get(Calendar.SECOND) * 1000;
	                        rv += d.get(Calendar.MILLISECOND);
	                    }
	                }else{
	                    rv = (afend.getTime() - afBegin.getTime()) + (mgEnd.getTime() - mgBegin.getTime());
	                }
	            }
	        }
    	} catch (ParseException e) {
			e.printStackTrace();
		}
        return rv;
    }

    //核心計算函式,返回毫秒
    private long getDayMiLLI(Calendar c1, Calendar c2){
        long beginL = 0;//開始天時間
        long endL   = 0;//結束天時間
        long rv     = 0;
        //int bh = c1.get(Calendar.HOUR_OF_DAY);//開始
        //int eh = c2.get(Calendar.HOUR_OF_DAY);//結束
        SimpleDateFormat format = new SimpleDateFormat("HH:mm");
    	String bhTime = format.format(c1.getTime());
    	String ehTime = format.format(c2.getTime());
    	try {
    		Date bh = format.parse(bhTime);
    		Date eh = format.parse(ehTime);
			Date mgBegin = format.parse(morningBegin);
			Date mgEnd = format.parse(morningEnd);
			Date afBegin = format.parse(afternoonBegin);
			Date afend = format.parse(afternoonEnd);
	        //如果開始日期和結束日期不是同一天,開始往前計算
	        if (c1.get(Calendar.YEAR) != c2.get(Calendar.YEAR) || c1.get(Calendar.MONTH) != c2.get(Calendar.MONTH) || c1.get(Calendar.DAY_OF_MONTH) != c2.get(Calendar.DAY_OF_MONTH)){
	            //不是同一天
	            beginL = getDayMiLLI(c1, true);
	            endL = getDayMiLLI(c2, false);
	            rv = beginL + endL;
	            c1.add(Calendar.DATE, 1);
	            while (c1.get(Calendar.YEAR) != c2.get(Calendar.YEAR) || c1.get(Calendar.MONTH) != c2.get(Calendar.MONTH) || c1.get(Calendar.DAY_OF_MONTH) != c2.get(Calendar.DAY_OF_MONTH)){
	                if (!isHodliDays(c1)){
	                    if (!isWeek(c1)){
	                        rv += (afend.getTime() - afBegin.getTime()) + (mgEnd.getTime() - mgBegin.getTime());
	                    }else{
	                        if (isPlusDay(c1)){
	                            rv += (afend.getTime() - afBegin.getTime()) + (mgEnd.getTime() - mgBegin.getTime());
	                        }
	                    }
	                }
	                c1.add(Calendar.DATE, 1);
	            }
	        }else{
	        	//是同一天
	            if (bh.getTime() < mgBegin.getTime()){
	                //開始時間小於早上開始時間,就等於說及計算結束時間在這一天的實際時間
	                rv += getDayMiLLI(c2, false);
	            }else{
	                if (eh.getTime() >= afend.getTime()){
	                    //結束時間大於下午結束時間,等於就是計算開始時間在這一天的實際時間
	                    rv += getDayMiLLI(c1, true);
	                }else{
	                    /**
	                     * 開始和結束都在中間時間段
	                     * 1.開始和結束都在上午
	                     * 2.開始和結束都在下午
	                     * 3.開始在上午,結束在下午
	                     * 4.開始在中間,結束不在
	                     * 5.結束在中間,開始不在
	                     * 6.開始和結束都在中間
	                     */
	
	                    if (eh.getTime() < mgEnd.getTime() || bh.getTime() >= afBegin.getTime()){
	                        //都在上午或者都在下午
	                        rv += eh.getTime() - bh.getTime();
	                        //rv -= c1.get(Calendar.MINUTE) * 60 * 1000;
	                        rv -= c1.get(Calendar.SECOND) * 1000;
	                        rv -= c1.get(Calendar.MILLISECOND);
	                        //rv += c2.get(Calendar.MINUTE) * 60 * 1000;
	                        rv += c2.get(Calendar.SECOND) * 1000;
	                        rv += c2.get(Calendar.MILLISECOND);
	                    }else if (bh.getTime() < mgEnd.getTime() && eh.getTime() >= afBegin.getTime()){
	                        //開始在上午,結束在下午
	                        rv += (eh.getTime() - bh.getTime()) - (afBegin.getTime() - mgEnd.getTime());
	                        //rv -= c1.get(Calendar.MINUTE) * 60 * 1000;
	                        rv -= c1.get(Calendar.SECOND) * 1000;
	                        rv -= c1.get(Calendar.MILLISECOND);
	                        //rv += c2.get(Calendar.MINUTE) * 60 * 1000;
	                        rv += c2.get(Calendar.SECOND) * 1000;
	                        rv += c2.get(Calendar.MILLISECOND);
	                    }else if (bh.getTime() < mgEnd.getTime() && eh.getTime() < afBegin.getTime()){
	                        //開始在上午,結束在中間
	                        rv += mgEnd.getTime() - bh.getTime();
	                       // rv -= c1.get(Calendar.MINUTE) * 60 * 1000;
	                        rv -= c1.get(Calendar.SECOND) * 1000;
	                        rv -= c1.get(Calendar.MILLISECOND);
	                    }else if (bh.getTime() > mgEnd.getTime() && eh.getTime() >= afBegin.getTime()){
	                        //開始在中間,結束在下午
	                        rv += eh.getTime() - afBegin.getTime();
	                        //rv += c2.get(Calendar.MINUTE) * 60 * 1000;
	                        rv += c2.get(Calendar.SECOND) * 1000;
	                        rv += c2.get(Calendar.MILLISECOND);
	                    }else{
	                       System.out.println("the begin time c1 " + c1.toString() + " and the end time c2 " + c2.toString() + " in not work day!");
	                    }
	                }
	            }
	        }
    	} catch (ParseException e) {
			e.printStackTrace();
		}
        return rv;
    }

    private Calendar getNew(Calendar begin){
        begin.add(Calendar.DATE, 1);
        begin.set(Calendar.HOUR_OF_DAY, Integer.valueOf(morningBegin.substring(0,2)));
        begin.set(Calendar.MINUTE, Integer.valueOf(morningBegin.substring(3,5)));
        begin.set(Calendar.SECOND, 0);
        return begin;
    }

    //核心計算函式,返回日期
    private Date func(Calendar begin, double hours){
        begin = getBeginDay(begin);
        //int h = begin.get(Calendar.HOUR_OF_DAY);
        SimpleDateFormat format = new SimpleDateFormat("HH:mm");
    	String bhTime = format.format(begin.getTime());
    	try {
    		Date h = format.parse(bhTime);
			Date mgBegin = format.parse(morningBegin);
			Date mgEnd = format.parse(morningEnd);
			Date afBegin = format.parse(afternoonBegin);
			Date afEnd = format.parse(afternoonEnd);
	        if (h.getTime() < mgBegin.getTime()){
	            //全天
	            if (hours > (((afEnd.getTime() - afBegin.getTime())/(double)3600000) + ((mgEnd.getTime() - mgBegin.getTime())/(double)3600000))){
	                begin = getNew(begin);
	                hours = hours - (((afEnd.getTime() - afBegin.getTime())/(double)3600000) + ((mgEnd.getTime() - mgBegin.getTime()))/(double)3600000);
	                return func(begin, hours);
	            }else{
	                /**
	                 * 這裡要判斷下,這個小時是否大於上午的工作時間,大於的話,時間就的到下午去了
	                 */
	                if (hours > ((mgEnd.getTime() - mgBegin.getTime())/(double)3600000)){
	                    begin.set(Calendar.HOUR_OF_DAY, Integer.valueOf(afternoonBegin.substring(0,2)));
	                    begin.set(Calendar.MINUTE, Integer.valueOf(afternoonBegin.substring(3,5)));
	                    hours = hours - ((mgEnd.getTime() - mgBegin.getTime())/(double)3600000);
	                }else{
	                    begin.set(Calendar.HOUR_OF_DAY, Integer.valueOf(morningBegin.substring(0,2)));
	                    begin.set(Calendar.MINUTE, Integer.valueOf(morningBegin.substring(3,5)));
	                }
	                //begin.set(Calendar.MINUTE, 0);
	                begin.set(Calendar.SECOND, 0);
	                begin.set(Calendar.MILLISECOND, 0);
	                long time = begin.getTime().getTime();
	                hours = hours * 60 * 60 * 1000;
	                time += hours;
	                return new Date(time);
	            }
	        }else if (h.getTime() >= afEnd.getTime()){
	            //過期,新增一天,重新算
	            begin.add(Calendar.DATE, 1);
	            return func(begin, hours);
	        }else{
	            //計算
	            long tm = getDayMiLLI(begin, true);//今天的時間
	            double houts_m = hours * 60 * 60 * 1000;
	            if (tm >= houts_m){
	                //不跨天,計算今天的
	                if (h.getTime() < mgEnd.getTime()){
	                    //在上午
	                    long rv = 0;
	                    rv += mgEnd.getTime() - h.getTime();
	                    //rv -= begin.get(Calendar.MINUTE) * 60 * 1000;
	                    rv -= begin.get(Calendar.SECOND) * 1000;
	                    rv -= begin.get(Calendar.MILLISECOND);
	                    if (houts_m > rv){
	                        //到下午
	                        begin.set(Calendar.HOUR_OF_DAY, Integer.valueOf(afternoonBegin.substring(0,2)));
		                    begin.set(Calendar.MINUTE, Integer.valueOf(afternoonBegin.substring(3,5)));
	                        begin.set(Calendar.SECOND, 0);
	                        begin.set(Calendar.MILLISECOND, 0);
	                        long time = begin.getTime().getTime();
	                        time += (houts_m - rv);
	                        return new Date(time);
	                    }else{
	                        //還在上午
	                        long time = begin.getTime().getTime();
	                        time += houts_m;
	                        return new Date(time);
	                    }
	                }else if (h.getTime() >= afBegin.getTime()){
	                    //在下午
	                    long time = begin.getTime().getTime();
	                    time += houts_m;
	                    return new Date(time);
	                }else{
	                    //在中間
	                	begin.set(Calendar.HOUR_OF_DAY, Integer.valueOf(afternoonBegin.substring(0,2)));
		                begin.set(Calendar.MINUTE, Integer.valueOf(afternoonBegin.substring(3,5)));
	                    begin.set(Calendar.SECOND, 0);
	                    begin.set(Calendar.MILLISECOND, 0);
	                    long time = begin.getTime().getTime();
	                    time += houts_m;
	                    return new Date(time);
	                }
	            }else{
	                //跨天,到第二天
	                begin = getNew(begin);
	                hours = (houts_m - tm) / (double)3600000;
	                return func(begin, hours);
	            }
	        }
    	}catch (ParseException e) {
			e.printStackTrace();
			return null;
		}
    }

修改的部分是支援了不是整點上下班的問題。