/**
* 以上班时间为准计算处理响应时间。
*/
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