主要用来计算工作时间时长,去除了休息日以及午休时间
package net.pakpobox.server.common.service.impl;
import net.pakpobox.server.common.service.CalculateHoursUtilsService;
import net.pakpobox.server.item.repository.HuaWeiCalendarDao;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
@Service
public class CalculateHoursUtilsServiceImpl implements CalculateHoursUtilsService {
@Autowired
private HuaWeiCalendarDao huaWeiCalendarDao;
private static Logger logger = LogManager.getLogger(CalculateHoursUtilsServiceImpl.class);
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); //这里的格式可以自己设置
//求工作时间内的时间间隔
public float calculateHours(int abh, int abm, int peh, int pem, String beginTime, String endTime, int aeh, int aem, int pbh, int pbm) {
float h1 = abh + (float) abm / 60;//上午上班时间
float h4 = peh + (float) pem / 60;//下午下班时间
float h2 = aeh + (float) aem / 60;//上午下班时间
float h3 = pbh + (float) pbm / 60;//下午上班时间
float hoursPerDay = h2 - h1 + h4 - h3;//每天上班小时数
int daysPerWeek = 7;//每周工作天数
long milsecPerDay = 1000 * 60 * 60 * 24;//每天的毫秒数
float hoursPerWeek = hoursPerDay * daysPerWeek;//每星期小时数
//logger.info("设置的上班时间为:" + abh + ":" + abm + "-" + aeh + ":" + aem
// + " " + pbh + ":" + pbm + "-" + peh + ":" + pem);
//logger.info("每天工作时间为:" + hoursPerDay + "小时");
//对输入的字符串形式的时间进行转换
Date t1 = stringToDate(beginTime);//真实开始时间
Date t2 = stringToDate(endTime);//真实结束时间
logger.info("设置的开始时间为:" + printDate(t1));
logger.info("设置的结束时间为:" + printDate(t2));
//起始时间到终止时间内的假期天数
int days = (int) ((t2.getTime() - t1.getTime()) / milsecPerDay);
int holiday = huaWeiCalendarDao.countByDate(dateTostring(t1), dateTostring(t2));
System.out.println(holiday);
//对时间进行预处理
t1 = processBeginTime(abh, abm, h1, h4, milsecPerDay, t1, pbh, pbm, h2, h3);
t2 = processEndTime(peh, pem, h1, h4, milsecPerDay, t2, aeh, aem, h2, h3);
logger.info("预处理后的开始时间为:" + printDate(t1));
logger.info("预处理后的结束时间为:" + printDate(t2));
//若开始时间晚于结束时间,返回0
if (t1.getTime() > t2.getTime()) {
logger.info("总工作时间为:0小时");
return 0;
}
//开始时间到结束时间的完整星期数
// int weekCount = (int) ((t2.getTime() - t1.getTime()) / (milsecPerDay * 7));
int weekCount = (int) ((t2.getTime() - t1.getTime()) / milsecPerDay);
logger.info("时间间隔内共包含了" + weekCount + "个完整的天数");
float totalHours = 0;
//totalHours += weekCount * hoursPerWeek - holiday * hoursPerDay;
//重开始到结束包含的工作时长
totalHours += (weekCount - holiday + (days - weekCount)) * hoursPerDay;
//调整结束时间,使开始时间和结束时间在一个星期的周期之内
//t2.setTime(t2.getTime() - weekCount * 7 * milsecPerDay);
t2.setTime(t2.getTime() - weekCount * milsecPerDay);
logger.info("结束时间调整为:" + printDate(t2));
int dayCounts = 0;//记录开始时间和结束时间之间工作日天数
//调整开始时间,使得开始时间和结束时间在同一天,或者相邻的工作日内。
while (t1.getTime() <= t2.getTime()) {
System.out.println(t1);
Date temp = new Date(t1.getTime() + milsecPerDay);
temp = processBeginTime(abh, abm, h1, h4, milsecPerDay, temp, pbh, pbm, h2, h3);
temp.setHours(t1.getHours());
temp.setMinutes(t1.getMinutes());
if (temp.getTime() > t2.getTime()) {
break;
} else {
t1 = temp;
dayCounts++;
}
}
logger.info("开始时间向后移动了" + dayCounts + "个工作日");
logger.info("开始时间调整为:" + printDate(t1));
totalHours += dayCounts * hoursPerDay;
float hh1 = t1.getHours() + (float) t1.getMinutes() / 60;
float hh2 = t2.getHours() + (float) t2.getMinutes() / 60;
//处理开始结束是同一天的情况
if (t1.getDay() == t2.getDay()) {
float tt = 0;
tt = hh2 - hh1;
//减去中午时间
if (hh1 >= h1 && hh1 <= h2 && hh2 >= h3) {
tt = tt - (h3 - h2);
}
totalHours += tt;
} else {
//处理开始结束不是同一天的情况
float tt1 = h4 - hh1;
float tt2 = hh2 - h1;
//减去中午时间
if (hh1 <= h2) {
tt1 = tt1 - (h3 - h2);
}
if (hh2 >= h3) {
tt2 = tt2 - (h3 - h2);
}
totalHours += (tt1 + tt2);
}
logger.info("总工作时间为:" + totalHours + "小时");
return totalHours;
}
/**
* 格式化输出时间: yyyy-mm-dd hh:mm:ss 星期x
*
* @param t
* @return
*/
private String printDate(Date t) {
String str;
String xingqi = null;
switch (t.getDay()) {
case 0:
xingqi = "星期天";
break;
case 1:
xingqi = "星期一";
break;
case 2:
xingqi = "星期二";
break;
case 3:
xingqi = "星期三";
break;
case 4:
xingqi = "星期四";
break;
case 5:
xingqi = "星期五";
break;
case 6:
xingqi = "星期六";
break;
default:
break;
}
str = format.format(t) + " " + xingqi;
return str;
}
/**
* 对结束时间进行预处理,使其处于工作日内的工作时间段内
*
* @param t
* @return
*/
private Date processEndTime(int peh, int pem, float h1, float h4, Long milsecPerDay, Date t, int aeh, int aem, float h2, float h3) {
float h = t.getHours() + (float) t.getMinutes() / 60;
//若结束时间晚于下午下班时间,将其设置为下午下班时间
if (h >= h4) {
t.setHours(peh);
t.setMinutes(pem);
} else {
//若结束时间介于中午休息时间,那么设置为上午下班时间
if (h >= h2 && h <= h3) {
t.setHours(aeh);
t.setMinutes(aem);
} else {
//若结束时间早于上午上班时间,日期向前推一天,并将时间设置为下午下班时间
if (t.getHours() <= h1) {
t.setTime(t.getTime() - milsecPerDay);
t.setHours(peh);
t.setMinutes(pem);
}
}
}
//若结束时间是周末,那么将结束时间向前推移到最近的工作日的下午下班时间,若为华为规定时间
/* if (t.getDay() == 0 || t.getDay() == 6) {
t.setTime(t.getTime() - milsecPerDay * (t.getDay() == 6 ? 1 : 2));
t.setHours(peh);
t.setMinutes(pem);
}*/
// //若结束时间是日历休息时间,那么将结束时间向前推移到最近的工作日的下午下班时间,若为规定时间
int de = huaWeiCalendarDao.loadbyDate(dateTostring(t));
SimpleDateFormat df = new SimpleDateFormat("yyyy/MM/dd");
if (de > 0) {
for (int i = 1; i < 365; i++) {
t = stringTodate(df.format(new Date(t.getTime() - 1 * 24 * 60 * 60 * 1000)));
int deae = huaWeiCalendarDao.loadbyDate(dateTostring(t));
if (deae == 0) {
t.setTime(t.getTime());
t.setHours(peh);
t.setMinutes(pem);
break;
}
}
}
return t;
}
//获取今日日期
public String toDayDate() {
Date d = new Date();
System.out.println(d);
SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd");
String dateNowStr = sdf.format(d);
return dateNowStr;
}
/**
* 对开始时间进行预处理
*
* @param t
* @return
*/
private Date processBeginTime(int abh, int abm, float h1, float h4, Long milsecPerDay, Date t, int pbh, int pbm, float h2, float h3) {
float h = t.getHours() + (float) t.getMinutes() / 60;
//若开始时间晚于下午下班时间,将开始时间向后推一天
if (h >= h4) {
t.setTime(t.getTime() + milsecPerDay);
t.setHours(abh);
t.setMinutes(abm);
} else {
//若开始时间介于中午休息时间,那么设置为下午上班时间
if (h >= h2 && h <= h3) {
t.setHours(pbh);
t.setMinutes(pbm);
} else {
//若开始时间早于上午上班时间,将hour设置为上午上班时间
if (t.getHours() <= h1) {
t.setHours(abh);
t.setMinutes(abm);
}
}
}
//若开始时间是周末,那么将开始时间向后推移到最近的工作日的上午上班时间
/* if (t.getDay() == 0 || t.getDay() == 6) {
t.setTime(t.getTime() + milsecPerDay * (t.getDay() == 6 ? 2 : 1));
t.setHours(abh);
t.setMinutes(abm);
}*/
//判断今天日期是否是放假日期,是的话则推后到最近工作日上午上班时间
//改时间是否为休息日
int de = huaWeiCalendarDao.loadbyDate(dateTostring(t));
SimpleDateFormat df = new SimpleDateFormat("yyyy/MM/dd");
System.out.println(de);
if (de > 0) {
for (int i = 1; i < 365; i++) {
t = stringTodate(df.format(new Date(t.getTime() + 1 * 24 * 60 * 60 * 1000)));
int deae = huaWeiCalendarDao.loadbyDate(dateTostring(t));
if (deae == 0) {
System.out.println(deae);
t.setTime(t.getTime());
System.out.println(t);
t.setHours(abh);
t.setMinutes(abm);
break;
}
}
}
return t;
}
/**
* 将字符串形式的时间转换成Date形式的时间
*
* @param time
* @return
*/
private Date stringToDate(String time) {
try {
return format.parse(time);
} catch (ParseException e) {
e.printStackTrace();
return null;
}
}
/**
* 将字符串形式的时间转换成Date形式的时间
*
* @param time
* @return
*/
private Date stringTodate(String time) {
try {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd");
return sdf.parse(time);
} catch (ParseException e) {
e.printStackTrace();
return null;
}
}
/**
* 将Date形式的时间转换成String形式的时间
*
* @param date
* @return
*/
private String dateTostring(Date date) {
DateFormat format = new SimpleDateFormat("yyyy/MM/dd");
String str = format.format(date); //2013-01-14
return str;
}
}