工作时间计算

/**
 * 以上班时间为准计算处理响应时间。
 */
public class ProcessTime {
 
    /*一天的4个时间点:上班,午休开始,午休结束,下班。早上09:00~12:00,下午13:00~18:00。*/
    /**上班时间小时*/
    static int BEGIN_HOUR   = 9;
    /**上班时间分钟*/
    static int BEGIN_MINUTE = 0;
 
    /**午休开始时间小时*/
    static int REST_BEGIN_HOUR   = 12;
    /**午休开始时间分钟*/
    static int REST_BEGIN_MINUTE = 0;
     
    /**午休结束时间小时*/
    static int REST_END_HOUR     = 13;
    /**午休结束时间分钟*/
    static int REST_END_MINUTE   = 0;
     
    /**下班时间小时*/
    static int END_HOUR     = 18;
    /**下班时间分钟*/
    static int END_MINUTE   = 0;
     
    /**上班到下班时间*/
    static float DAY_HOUR  = 0F;
    /**一天工作时间*/
    static float WORK_HOUR = 0F;
    /**午休时间*/
    static float REST_HOUR = 0F;
    static{
        DAY_HOUR = ((END_HOUR*60+END_MINUTE)-(BEGIN_HOUR*60+BEGIN_MINUTE))/60F;
        REST_HOUR = ((REST_END_HOUR*60+REST_END_MINUTE)-(REST_BEGIN_HOUR*60+REST_BEGIN_MINUTE))/60F;
        WORK_HOUR = DAY_HOUR - REST_HOUR;
    }
     
    /**
     * 取两个时间点间的总上班时间,如下班前5分钟派单,次日上班后5分钟解决,响应时间算10分钟。
     * @param beginDate 开始日期,格式yyyy-mm-dd hh:mm:ss
     * @param endDate 结束日期,格式yyyy-mm-dd hh:mm:ss
     * @return 保留两位小数的小时数
     */
    public static float getHoursBetween(String beginDate, String endDate){
         
        /*看开始日期是否是周末或节假日*/
        String beginDate10 = beginDate.substring(0,10);
        String endDate10 = endDate.substring(0,10);
         
        float totalHour = 0F;
        boolean isNormal = false;   //判断开始日期是否是周末或节假日
        /*判断是否算开始日期*/
        if(isWeekEnd(beginDate10) || isHoliday(beginDate10)){
        }else{
            isNormal = true;
            int beginHour = Integer.parseInt(beginDate.substring(11,13));
            int beginMinute = Integer.parseInt(beginDate.substring(14,16));
            if(beginHour * 60 + beginMinute < END_HOUR * 60 + END_MINUTE){//下班后不算当天时间
                //开始时间在午休时间里 向后原则
                if(isMiddayRest(beginHour, beginMinute)){
                    beginHour = REST_END_HOUR;
                    beginMinute = REST_END_MINUTE;
                }
                totalHour = (END_HOUR * 60 + END_MINUTE - beginHour * 60 - beginMinute)/60F;
                 
                //开始时间在午休前必须去掉午休时间
                if((beginHour * 60 + beginMinute) < (REST_BEGIN_HOUR * 60 + REST_BEGIN_MINUTE)){
                    totalHour -= REST_HOUR;
                }
            }
        }
        /*判断是否算结束日期*/
        if(isWeekEnd(endDate10) || isHoliday(endDate10)){
        }else{
            int endHour = Integer.parseInt(endDate.substring(11,13));
            int endMinute = Integer.parseInt(endDate.substring(14,16));
            if(endHour * 60 + endMinute > BEGIN_HOUR * 60 + BEGIN_MINUTE){//上班前不算当天时间
                //结束时间在午休时间里 向前原则
                if(isMiddayRest(endHour, endMinute)){
                    endHour = REST_BEGIN_HOUR;
                    endMinute = REST_BEGIN_MINUTE;
                }
                totalHour += (endHour * 60 + endMinute - BEGIN_HOUR * 60 - BEGIN_MINUTE)/60F;
                 
                //结束时间在午休后必须去掉午休时间
                if((endHour * 60 + endMinute) > (REST_END_HOUR * 60 + REST_END_MINUTE)){
                    totalHour -= REST_HOUR;
                }
            }
        }
         
        /*开始日期与结束日期是否同一天并且都不是周末或节假日*/
        if(beginDate10.compareTo(endDate10) == 0 && isNormal){
            totalHour -= WORK_HOUR;//同一天需要减去工作时长,因为开始时间算到下班,结束时间从上班开始算
        }else{
            //加上两日期间非周末、非节假日的工作时间
            totalHour +=  getDaysBetween(beginDate10, endDate10).size() * WORK_HOUR;
        }
         
        return Float.parseFloat(new DecimalFormat("#.00").format(totalHour));
    }
     
    /**
     * 判断当前时间是否是午休时间
     * @param hour
     * @param minute
     * @return
     */
    private static boolean isMiddayRest(int hour, int minute){
        int begin = REST_BEGIN_HOUR * 60 + REST_BEGIN_MINUTE;
        int end   = REST_END_HOUR * 60 + REST_END_MINUTE;
        int temp  = hour * 60 + minute;
        return begin <= temp && temp <= end;
    }
     
    /**
     * 以yyyy-mm-dd的格式取得两日期间非周末、非节假日的日期列表
     * @param beginDate 开始日期,格式yyyy-mm-dd
     * @param endDate 结束日期,格式yyyy-mm-dd
     * @return ArrayList日期列表
     */
    private static ArrayList<String> getDaysBetween(String beginDate, String endDate){
        ArrayList<String> days = new ArrayList<String>();
        //开始日期必须比结束日期小
        if(beginDate.compareTo(endDate) < 0){
            Calendar cal = Calendar.getInstance();
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            String temp = beginDate;
            while(true){
                //取得下一天与结束日期比较
                String[] ymd = temp.split("-");
                cal.set(Integer.parseInt(ymd[0]), Integer.parseInt(ymd[1])-1, Integer.parseInt(ymd[2]));
                cal.add(Calendar.DATE, 1);
                temp = sdf.format(cal.getTime());
                if(temp.compareTo(endDate) == 0){
                    break;
                }
                if(isWeekEnd(temp) || isHoliday(temp)){
                }else{
                    days.add(temp);//不是周末也不是节假日
                }
            }
        }
        return days;
    }
    /**
     * 判断是否是周末
     * @param yyyy_MM_dd 以yyyy-mm-dd的日期格式,如2007-09-29
     * @return
     */
    private static boolean isWeekEnd(String yyyy_MM_dd){
        String[] temp = yyyy_MM_dd.split("-");
        return isWeekEnd(Integer.parseInt(temp[0]),Integer.parseInt(temp[1]),Integer.parseInt(temp[2]));
    }
    /**
     * 判断是否是周末
     * @param year 年
     * @param month 月
     * @param date 日
     * @return
     */
    private static boolean isWeekEnd(int year, int month, int date){
        Calendar cal = Calendar.getInstance();
        cal.set(year, month-1, date);
        int dayOfWeek = cal.get(Calendar.DAY_OF_WEEK); 
        if( dayOfWeek == Calendar.SATURDAY || dayOfWeek == Calendar.SUNDAY){
            return true;
        }
        return false;
    }
    /**
     * 判断是否是节假日
     * @param yyyy_MM_dd yyyy_MM_dd 以yyyy-mm-dd的日期格式,如2007-09-29
     * @return
     */
    private static boolean isHoliday(String yyyy_MM_dd){
        //TODO:判断假日,实际从数据库读取
        ArrayList<String> holiday = new ArrayList<String>();
        holiday.add("2007-10-01");
        holiday.add("2007-10-02");
        holiday.add("2007-10-03");
        holiday.add("2007-05-01");
        holiday.add("2007-05-02");
        holiday.add("2007-05-03");
        holiday.add("2007-01-01");
        return holiday.contains(yyyy_MM_dd);
    }
    /**
     * 判断是否是节假日
     * @param year 年
     * @param month 月
     * @param date 日
     * @return
     */
    public static boolean isHoliday(int year, int month, int date){
        String m = "";
        if(month < 10){
            m = "0" + month;
        }
        String d = "";
        if(date < 10){
            d = "0" + d;
        }
        return isHoliday(year + "-" + m + "-" + d);
    }
    /**
     * 判断日期是否是格式为yyyy-mm-dd hh:mm:ss的合法日期
     * @param date
     * @return
     */
    public static boolean isDayTime(String date){
        boolean flag = true;
        try{
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            if(!date.equals(sdf.format(sdf.parse(date)))){
                flag = false;
            }
        }catch(Exception e){
            flag = false;
        }
        return flag;
    }
     
    public static void main(String[] args){
        System.out.println(getHoursBetween("2007-10-08 11:20:30","2007-10-08 13:01:30"));
    }
}

转载于:https://my.oschina.net/h2do/blog/268095

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值