public static void main(String[] args) {
// 设置开始时间和结束时间
String startTimeStr = "2024-05-07 17:00";
String endTimeStr = "2024-05-07 22:20";
// 时间格式化器
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");
// 将字符串转换为 LocalDateTime 对象
LocalDateTime startTime = LocalDateTime.parse(startTimeStr, formatter);
LocalDateTime endTime = LocalDateTime.parse(endTimeStr, formatter);
// 定义午休时间
LocalTime wxStartTime = LocalTime.parse("11:40");
LocalTime wxEndTime = LocalTime.parse("13:30");
// 定义晚修时间
LocalTime eveningStartTime = LocalTime.parse("17:30");
LocalTime eveningEndTime = LocalTime.parse("18:30");
// 计算总工作分钟数
long totalMinutes = Duration.between(startTime, endTime).toMinutes();
// 初始化减去的午休和晚修分钟数
long deductedMinutes = 0;
// 处理跨天的时间跨度
LocalDateTime currentDayStart = startTime;
// 循环遍历每一天,支持多天
while (!currentDayStart.toLocalDate().isEqual(endTime.toLocalDate())) {
LocalDate date = currentDayStart.toLocalDate();
// 当天的结束时间是午夜
LocalDateTime currentDayEnd = LocalDateTime.of(date, LocalTime.of(23, 59));
if (currentDayStart.isBefore(currentDayEnd) && currentDayEnd.isBefore(endTime)) {
// 在当前日期内,计算午休时间的重叠部分
LocalDateTime lunchStart = LocalDateTime.of(date, wxStartTime);
LocalDateTime lunchEnd = LocalDateTime.of(date, wxEndTime);
deductedMinutes = getDeductedMinutes(currentDayStart, currentDayEnd, deductedMinutes, lunchStart, lunchEnd);
// 在当前日期内,计算晚修时间的重叠部分
LocalDateTime eveningStart = LocalDateTime.of(date, eveningStartTime);
LocalDateTime eveningEnd = LocalDateTime.of(date, eveningEndTime);
deductedMinutes = getDeductedMinutes(currentDayStart, currentDayEnd, deductedMinutes, eveningStart, eveningEnd);
}
currentDayStart = currentDayStart.plusDays(1).with(LocalTime.MIN);
}
// 检查最后一天(结束时间所在的那一天)的午休和晚修时间
LocalDate date = endTime.toLocalDate();
LocalDateTime lunchStart = LocalDateTime.of(date, wxStartTime);
LocalDateTime lunchEnd = LocalDateTime.of(date, wxEndTime);
LocalDateTime eveningStart = LocalDateTime.of(date, eveningStartTime);
LocalDateTime eveningEnd = LocalDateTime.of(date, eveningEndTime);
deductedMinutes = getDeductedMinutes(startTime, endTime, deductedMinutes, lunchStart, lunchEnd);
deductedMinutes = getDeductedMinutes(startTime, endTime, deductedMinutes, eveningStart, eveningEnd);
// 计算实际工作时间
long actualWorkMinutes = totalMinutes - deductedMinutes;
// 将实际工作时间转换为小时的小数形式
double actualWorkHours = actualWorkMinutes / 60.0;
// 将实际工作时间保留两位小数
// 使用 Math.round() 方法将实际工作时间四舍五入到两位小数
double v = Math.round(actualWorkHours * 100.0) / 100.0;
// 输出结果
System.out.println("实际工作时间:" + actualWorkMinutes / 60 + "小时 " + actualWorkMinutes % 60 + "分钟-----" + actualWorkMinutes);
System.out.println("实际工作时间:" + v + "小时");
}
/**
* 计算重叠部分的分钟数
* @param startTime 开始时间
* @param endTime 结束时间
* @param deductedMinutes 已经减去的分钟数
* @param restTimeStart 休息开始时间
* @param restTimeEnd 休息结束时间
* @return 重叠部分的分钟数
*/
private static long getDeductedMinutes(LocalDateTime startTime, LocalDateTime endTime, long deductedMinutes, LocalDateTime restTimeStart, LocalDateTime restTimeEnd) {
if (startTime.isBefore(restTimeEnd) && endTime.isAfter(restTimeStart)) {
LocalDateTime overlapStart = startTime.isAfter(restTimeStart) ? startTime : restTimeStart;
LocalDateTime overlapEnd = endTime.isBefore(restTimeEnd) ? endTime : restTimeEnd;
deductedMinutes += Duration.between(overlapStart, overlapEnd).toMinutes();
}
return deductedMinutes;
}