记得画图很重要,看坐标!
import java.math.BigDecimal;
import java.time.Duration;
import java.time.LocalTime;
public class Test {
public double calculateWorkHours(LocalTime startTime, LocalTime endTime, LocalTime morningStart, LocalTime morningEnd, LocalTime afternoonStart, LocalTime afternoonEnd) {
// 如果结束时间在开始时间之前,表示跨天,需要调整为第二天的时间
if (endTime.isBefore(startTime)) {
// endTime = endTime.plusDays(1);
}
// 计算在上下班打卡时间内的时间段
LocalTime workStart = startTime.isBefore(morningStart) ? morningStart : startTime;
LocalTime workEnd = endTime.isAfter(afternoonEnd) ? afternoonEnd : endTime;
// 如果工作开始时间在下午上班时间之后,或者工作结束时间在早上上班时间之前,表示不在上下班打卡时间内
if (workStart.isAfter(afternoonEnd) || workEnd.isBefore(morningStart)) {
return 0.0; // 不在上下班打卡时间内,返回0小时
}
// 减去上午上班打卡前的时间
if (workStart.isBefore(morningStart)) {
Duration beforeMorningStart = Duration.between(workStart, morningStart);
workStart = morningStart;
workEnd = workEnd.minus(beforeMorningStart);
}
// 减去下午下班打卡后的时间
if (workEnd.isAfter(afternoonEnd)) {
Duration afterAfternoonEnd = Duration.between(afternoonEnd, workEnd);
workEnd = afternoonEnd;
workStart = workStart.plus(afterAfternoonEnd);
}
// 计算在上下班打卡时间内的总时长
Duration duration = Duration.between(workStart, workEnd);
// 去掉休息时间 工作早上开始前-下午结束之间 减去中间的值
if (workStart.isBefore(morningEnd) && workEnd.isAfter(afternoonStart)) {//success 8h
Duration morningRest = Duration.between(morningEnd, afternoonStart);
duration = duration.minus(morningRest);
// if (workStart.isBefore(morningStart)) {
// duration = duration.minus(Duration.between(workStart, morningStart));
// }
// if (workEnd.isAfter(afternoonEnd)) {
// duration = duration.minus(Duration.between(afternoonEnd, workEnd));
// }
}
// 去掉休息时间 中午某段时间是多余的
// workStart.isBefore(morningStart) &&
if (workEnd.isBefore(afternoonStart) && workEnd.isAfter(morningEnd)) {
Duration morningRest = Duration.between(morningEnd, workEnd);
duration = duration.minus(morningRest);//前半部分已经自动取
// if (workStart.isBefore(morningStart)) {
// duration = duration.minus(Duration.between(workStart, morningStart));
// }
// if (workEnd.isAfter(afternoonEnd)) {
// duration = duration.minus(Duration.between(afternoonEnd, workEnd));
// }
}
// if (workStart.isBefore(afternoonStart) && workStart.isAfter(morningEnd)){
// Duration morningRest = Duration.between(morningEnd, afternoonStart);
// duration = duration.minus(morningRest);
// }
if (workStart.isBefore(afternoonStart) && workStart.isAfter(morningEnd)) {
Duration morningRest = Duration.between(workStart, afternoonStart);
duration = duration.minus(morningRest);
}
// 将时长转换为小时数,保留一位小数
double hours = duration.toMinutes() / 60.0;
BigDecimal bg = new BigDecimal(hours);
double f1 = bg.setScale(2, BigDecimal.ROUND_DOWN).doubleValue();//BigDecimal.ROUND_HALF_UP 四舍五入
//return Math.max(0.0, Math.round(hours * 10.0) / 10.0); // 保留一位小数,确保不返回负数
return f1; // 保留两位小数,确保不返回负数
}
public static void main(String[] args) {
Test attendanceService = new Test();
// LocalTime startTime = LocalTime.of(5, 50);
// LocalTime endTime = LocalTime.of(17, 30); //8h 正确
// LocalTime startTime = LocalTime.of(11, 10);
// LocalTime endTime = LocalTime.of(14, 40); //2h 正确
// LocalTime startTime = LocalTime.of(12, 59);
// LocalTime endTime = LocalTime.of(17, 31);// 3.83 小时 错误
// LocalTime startTime = LocalTime.of(6, 10);
// LocalTime endTime = LocalTime.of(13, 10);//4.16 =250/6
//--------------
LocalTime startTime = LocalTime.of(6, 10);
LocalTime endTime = LocalTime.of(18, 12);
LocalTime morningStart = LocalTime.of(8, 0);
LocalTime morningEnd = LocalTime.of(12, 10);
LocalTime afternoonStart = LocalTime.of(13, 40);
LocalTime afternoonEnd = LocalTime.of(17, 30);
double totalWorkHours = attendanceService.calculateWorkHours(startTime, endTime, morningStart, morningEnd, afternoonStart, afternoonEnd);
System.out.println("在上下班打卡时间内的日志记录小时数: " + totalWorkHours + " 小时");
}
}
有更好的方法请分享一下哈,我目前只想到这样的方法,只针对白班使用,大家有没有包括夜班的也能使用的方法推荐一下。