package com.dmsoft.mes.util;
import lombok.Data;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.Duration;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
/**
* 计算重叠时间段
* author: zhangweida
* date: 2023/4/28
*/
public class TimeCalculator {
private static long calculateOverlapMinutes(String startTimeStr, String endTimeStr) {
LocalDateTime startDateTime = LocalDateTime.parse(startTimeStr, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
LocalDateTime endDateTime = LocalDateTime.parse(endTimeStr, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
LocalTime time1120 = LocalTime.of(11, 20,0);
LocalTime time1220 = LocalTime.of(12, 20,0);
LocalTime time1700 = LocalTime.of(17, 0,0);
LocalTime time1800 = LocalTime.of(18, 0,0);
LocalTime time2259 = LocalTime.of(22, 59,59);
//这里为什么不是直接的00:00:00?因为是跨天的,如果是00:00:00会导致误差,所以往前推一秒,方便计算
LocalTime time2359 = LocalTime.of(23, 59,59);
long overlap = 0;
/**
* 重叠时间段1:11:20:00-12:20:00
* 重叠时间段2:17:00:00-18:00:00
* 重叠时间段3:22:59:59-23:59:59
*/
LocalDateTime overlapStart1 = LocalDateTime.of(startDateTime.toLocalDate(), time1120);
LocalDateTime overlapEnd1 = LocalDateTime.of(startDateTime.toLocalDate(), time1220);
LocalDateTime overlapStart2 = LocalDateTime.of(startDateTime.toLocalDate(), time1700);
LocalDateTime overlapEnd2 = LocalDateTime.of(startDateTime.toLocalDate(), time1800);
LocalDateTime overlapStart3 = LocalDateTime.of(startDateTime.toLocalDate(), time2259);
LocalDateTime overlapEnd3 = LocalDateTime.of(endDateTime.toLocalDate(), time2359);
if (startDateTime.isBefore(overlapEnd1) && endDateTime.isAfter(overlapStart1)) {
overlap += calculateOverlapMinutes(startDateTime, endDateTime, overlapStart1, overlapEnd1);
}
if (startDateTime.isBefore(overlapEnd2) && endDateTime.isAfter(overlapStart2)) {
overlap += calculateOverlapMinutes(startDateTime, endDateTime, overlapStart2, overlapEnd2);
}
if (startDateTime.isBefore(overlapEnd3) && endDateTime.isAfter(overlapStart3)) {
overlap += calculateOverlapMinutes(startDateTime, endDateTime, overlapStart3, overlapEnd3);
}
return overlap;
}
private static long calculateOverlapMinutes(LocalDateTime startDateTime, LocalDateTime endDateTime,
LocalDateTime overlapStart, LocalDateTime overlapEnd) {
LocalDateTime overlapStartMax = startDateTime.isBefore(overlapStart) ? overlapStart : startDateTime;
LocalDateTime overlapEndMin = endDateTime.isAfter(overlapEnd) ? overlapEnd : endDateTime;
return overlapStartMax.until(overlapEndMin, java.time.temporal.ChronoUnit.MINUTES);
}
public static List<TimeRange> splitTime(String startTime, String endTime) throws ParseException {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date startDate = sdf.parse(startTime);
Date endDate = sdf.parse(endTime);
List<TimeRange> result = new ArrayList<>();
Calendar startCal = Calendar.getInstance();
startCal.setTime(startDate);
Calendar endCal = Calendar.getInstance();
endCal.setTime(endDate);
if (startCal.get(Calendar.YEAR) == endCal.get(Calendar.YEAR)
&& startCal.get(Calendar.DAY_OF_YEAR) == endCal.get(Calendar.DAY_OF_YEAR)) {
result.add(new TimeRange(startTime, endTime));
} else {
while (startCal.before(endCal)) {
String s = sdf.format(startCal.getTime());
startCal.set(Calendar.HOUR_OF_DAY, 23);
startCal.set(Calendar.MINUTE, 59);
startCal.set(Calendar.SECOND, 59);
String e = sdf.format(startCal.getTime());
if (startCal.get(Calendar.YEAR) == endCal.get(Calendar.YEAR)
&& startCal.get(Calendar.DAY_OF_YEAR) == endCal.get(Calendar.DAY_OF_YEAR)) {
e = endTime;
}
result.add(new TimeRange(s, e));
startCal.add(Calendar.DATE, 1);
startCal.set(Calendar.HOUR_OF_DAY, 0);
startCal.set(Calendar.MINUTE, 0);
startCal.set(Calendar.SECOND, 0);
}
}
return result;
}
public static long totalOverlapMinutes(String startTime,String endTime) throws ParseException {
long overlapMinutes = 0;
List<TimeRange> timeRanges = splitTime(startTime, endTime);
for (int i = 0; i < timeRanges.size(); i++) {
overlapMinutes += calculateOverlapMinutes(timeRanges.get(i).getStartTime(), timeRanges.get(i).getEndTime());
}
return overlapMinutes;
}
public static void main(String[] args) throws ParseException {
long l = totalOverlapMinutes("2023-04-26 23:30:09", "2023-04-26 23:59:59");
System.out.println(l);
}
}
@Data
class TimeRange {
private String startTime;
private String endTime;
public TimeRange(String startTime, String endTime) {
this.startTime = startTime;
this.endTime = endTime;
}
@Override
public String toString() {
return "{'startTime': '" + startTime + "', 'endTime': '" + endTime + "'}";
}
}
09-30
1194
![](https://csdnimg.cn/release/blogv2/dist/pc/img/readCountWhite.png)
09-26
3569
![](https://csdnimg.cn/release/blogv2/dist/pc/img/readCountWhite.png)