/**
* @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;
}
}