需求:计算两个时间之间的工作时间,比如:
计算两个时间的时间差,但是中间有部分时间是要去掉的,比如计算2023-09-10 10:00:00 和 2023-09-15 16:00:00 的时间差,但是要刨除掉17:30~08:30和11:00~13:00的时间,因为这两个时间不是工作时间,同时如果2023-09-10~2023-09-15之间有周末、节假日也要剔除,最终算出来的时长应该是34小时
代码如下:
import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
public class TimeWorkingHoursCalculator {
private static final DateTimeFormatter TIME_FORMAT = DateTimeFormatter.ofPattern("HH:mm");
private static final DateTimeFormatter DATE_FORMAT = DateTimeFormatter.ofPattern("yyyy-MM-dd");
private LocalTime morningStartTime;
private LocalTime morningEndTime;
private LocalTime afternoonStartTime;
private LocalTime afternoonEndTime;
private List<LocalDate> specialRestDays ;
public static void main(String[] args) {
// 设置工作时间段
LocalTime morningStartTime = LocalTime.parse("08:30", TIME_FORMAT);
LocalTime morningEndTime = LocalTime.parse("11:30", TIME_FORMAT);
LocalTime afternoonStartTime = LocalTime.parse("13:00", TIME_FORMAT);
LocalTime afternoonEndTime = LocalTime.parse("17:00", TIME_FORMAT);
// 创建工作时间计算器
TimeWorkingHoursCalculator calculator = new TimeWorkingHoursCalculator(morningStartTime, morningEndTime,
afternoonStartTime, afternoonEndTime);
// 设置特殊休息日
LocalDate specialRestDay1 = LocalDate.parse("2023-07-01", DATE_FORMAT);
LocalDate specialRestDay2 = LocalDate.parse("2023-09-12", DATE_FORMAT);
calculator.addSpecialRestDay(specialRestDay1);
calculator.addSpecialRestDay(specialRestDay2);
// 计算工作小时数
LocalDateTime startTime = LocalDateTime.parse("2023-09-11T10:00", DateTimeFormatter.ISO_LOCAL_DATE_TIME);
LocalDateTime endTime = LocalDateTime.parse("2023-09-15T16:00", DateTimeFormatter.ISO_LOCAL_DATE_TIME);
double workingHours = calculator.calculateWorkingHours(startTime, endTime);
System.out.println("工作小时数:" + workingHours);
}
public TimeWorkingHoursCalculator(LocalTime morningStartTime, LocalTime morningEndTime,
LocalTime afternoonStartTime, LocalTime afternoonEndTime) {
this.morningStartTime = morningStartTime;
this.morningEndTime = morningEndTime;
this.afternoonStartTime = afternoonStartTime;
this.afternoonEndTime = afternoonEndTime;
this.specialRestDays = new ArrayList<>();
}
public void addSpecialRestDay(LocalDate date) {
specialRestDays.add(date);
}
public double calculateWorkingHours(LocalDateTime startTime, LocalDateTime endTime) {
double totalHours = 0.0;
LocalDateTime currentDateTime = startTime;
while (currentDateTime.isBefore(endTime) || currentDateTime.compareTo(endTime) == 0) {
LocalDate currentDate = currentDateTime.toLocalDate();
if (!isWeekend(currentDate) && !isSpecialRestDay(currentDate)) {
LocalTime currentTime = currentDateTime.toLocalTime();
boolean isMorningWorkingHour = currentTime.isAfter(morningStartTime)
&& (currentTime.isBefore(morningEndTime) || currentTime.compareTo(morningEndTime) == 0)
&& currentDateTime.compareTo(startTime)!=0;//当开始时间为08:30(工作开始时间)时,会导致多出半小时,所以需要增加这个判断
boolean isAfternoonWorkingHour = currentTime.isAfter(afternoonStartTime)
&& (currentTime.isBefore(afternoonEndTime) || currentTime.compareTo(afternoonEndTime) == 0 )
&& currentDateTime.compareTo(startTime)!=0;
// boolean isMorningWorkingHour = currentTime.isAfter(morningStartTime)
// boolean isAfternoonWorkingHour = currentTime.isAfter(afternoonStartTime) && currentTime.isBefore(afternoonEndTime);
if (isMorningWorkingHour || isAfternoonWorkingHour) {
totalHours += 0.5;
}
}
currentDateTime = currentDateTime.plusMinutes(30);//此处设置的步进是30分钟,可以根据自己需求进行调整,但调整的时候需要同步对totalHours的定义、步进进行调整
}
return totalHours;
}
private boolean isWeekend(LocalDate date) {
DayOfWeek dayOfWeek = date.getDayOfWeek();
return dayOfWeek == DayOfWeek.SATURDAY || dayOfWeek == DayOfWeek.SUNDAY;
}
private boolean isSpecialRestDay(LocalDate date) {
return specialRestDays.contains(date);
}
}