多段时间取并集或交集后的结果
需求:
有一个时间段列表,将列表中有重合的时间段取交集或并集合为一个时间段,不与其他时间段重合不变,输出结果列表
代码:
时间段类
@Data
@AllArgsConstructor
@NoArgsConstructor
public class TimePeriod {
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date beginTime;
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date endTime;
}
时间工具类
public class TimeUtils {
/**
* 获取日期中的最大或最小者
* @param maxOrMin true 最大值 false最小值
* @param dates 可变参数
* @return 最大或最小的日期
*/
public static Date getExtremumDate(Boolean maxOrMin,Date... dates){
List<Date> dates1 = new ArrayList<>(dates.length);
for (Date date : dates){
if (date != null){
dates1.add(date);
}
}
if (dates1.size() == 0){
return null;
}
if (maxOrMin){
return Collections.max(dates1);
}else {
return Collections.min(dates1);
}
}
/**
* 多个时间段取并集或交集后的时间段列表
* @param mixedOrUnion true:交集 | false:并集
* @param periods 时间段列表
* @return 时间并集 map beginTime -> endTime
*/
public static Map<Date, Date> getTimePeriodsUnion(Boolean mixedOrUnion,List<TimePeriod> periods) {
periods.sort(Comparator.comparing(TimePeriod::getBeginTime));
Map<Date, Date> dateMap = new TreeMap<>();
for (TimePeriod period : periods) {
Date startTime = period.getBeginTime();
Date endTime = period.getEndTime();
if (MapUtils.isEmpty(dateMap)) {
dateMap.put(startTime, endTime);
}
Map<Date, Date> tempMap = new TreeMap<>();
//TreeMap能自动根据Key排序,只需要合并交集
//1.有交集则合并或取交集
//2.没有交集则添加
Iterator<Entry<Date, Date>> iterator = dateMap.entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry<Date, Date> entry = iterator.next();
Date start = entry.getKey();
Date end = entry.getValue();
//两个时间段 [A, B)、[X, Y),X < B && A < Y 或者 A < Y && X < B则有交集
if ((startTime.before(end) && endTime.after(start)) || (start.before(endTime) && end.after(startTime))){
iterator.remove();
if (mixedOrUnion){
tempMap.put(TimeUtils.getExtremumDate(true,startTime,start),TimeUtils.getExtremumDate(false,endTime,end));
}else {
tempMap.put(TimeUtils.getExtremumDate(false,startTime,start),TimeUtils.getExtremumDate(true,endTime,end));
}
}else{
if (!iterator.hasNext()){
tempMap.put(startTime, endTime);
}
}
}
dateMap.putAll(tempMap);
}
return dateMap;
}
}