list<时间集合>在查询时间区间内的交集、并集、差集等

需求:
时间区间集合(0~N个时间区间)
在查询时间区间【beginTime,endTime】中 的交集、并集、差集
时间区间集合可以想象为 N个人员在某公司的工作时间,查询特定时间段1月中的工作情况。。
查询时间区间【beginTime,endTime】 = 【"2024-02-01 00:00:00","2024-02-29 23:59:59"】
    人员A工作时间【"2024-01-01 00:00:00","2024-02-15 23:59:59"】
    人员B工作时间【"2024-02-20 00:00:00","2024-03-31 23:59:59"】
    人员C工作时间【"2024-02-10 00:00:00","2024-02-15 23:59:59"】
    //人员D工作时间【"2024-01-01 00:00:00","2024-03-15 23:59:59"】
一、差集:查询时间区间内【无人】工作的时间区间,直接调用3即可
  1、单条取差集
    举例:三个人员在查询时间区间内不工作的时间,得出:
    人员A非工作时间【"2024-02-16 00:00:00","2024-02-29 23:59:59"】
    人员B非工作时间【"2024-02-01 00:00:00","2024-02-19 23:59:59"】
    人员C非工作时间【"2024-01-01 00:00:00","2024-02-09 23:59:59"】【"2024-02-16 00:00:00","2024-02-29 23:59:59"】
    //人员D非工作时间【NULL】
/*单条取差集
* 非工作的时间段——0、1个最多2个
* */
public static Map<String, Object> differences0(String beginTime,String endTime,List<Map<String,String>> inMainList){
Map<String, Object> outMap = new HashMap<String, Object>();
for(Map<String,String> inMainMap : inMainList){
List<Map<String,String>> outList = new ArrayList<Map<String, String>>();
if(beginTime.compareTo(inMainMap.get("startTime")) < 0){
Map<String,String> map = new HashMap<String, String>();
map.put("startTime", beginTime);
map.put("endTime", inMainMap.get("startTime"));
outList.add(map);
}
if(endTime.compareTo(inMainMap.get("endTime"))>0){
Map<String,String> map = new HashMap<String, String>();
map.put("startTime", inMainMap.get("endTime"));
map.put("endTime", endTime);
outList.add(map);
}
if(outList.size() == 0) {//没有差集表示 查询时间范围内全是有人在工作
outMap = new HashMap<String, Object>();
break;
}else{
outMap.put(inMainMap.get("mainUnit"), outList);
}
}
return outMap;
}
  2、所有单条差集区间的交集
/*所有的差集的交集
* * 例如:差集 人员A非工作时间【"2024-02-16 00:00:00","2024-02-29 23:59:59"】
*人员B非工作时间【"2024-02-01 00:00:00","2024-02-19 23:59:59"】
*人员C非工作时间【"2024-01-01 00:00:00","2024-02-09 23:59:59"】【"2024-01-16 00:00:00","2024-02-29 23:59:59"】
* 交集:【"2024-02-16 00:00:00","2024-02-19 23:59:59"】,即为无人工作时间
* */
public static List<Map<String, String>> getDateTimeIntersection(String beginTime,String endTime,
                                        List<Map<String,String>> inMainList){
Map<String, Object> outMap = differences0(beginTime, endTime, inMainList);
List<Map<String, String>> outMainList = new ArrayList<Map<String, String>>();
int i=0;
Boolean isIntersect = false;
for (Map.Entry<String, Object> entry : outMap.entrySet()) {
String mainUnit = entry.getKey();//人员标识:A/B/C
List<Map<String,String>> outList = (List<Map<String, String>>) entry.getValue();
     //单条工作记录产生的非工作时间段,能1个最多2个
if(i == 0){
outMainList.addAll(outList);
isIntersect = true;
}else {
isIntersect = false;
List<Map<String, String>> newOutMianList = new ArrayList<Map<String, String>>();
for (Map<String, String> outMain : outMainList){
for(Map<String, String> outAll : outList) {
Map<String, Object> result = getAllIndRange(outMain, outAll);
            //同个人员的多个不工作区间只要有一个与对比区间有交集就行
if ((Boolean) result.get("isIntersect")) {//有交集存起来,存储新的
isIntersect = true;
newOutMianList.add((Map<String, String>) result.get("result"));
}
}
}
outMainList = newOutMianList;
}
if(!isIntersect){//已无交集,跳出循环
break;
}
i++;
}
return outMainList;
}
3、2中调用的其他方法
/*两个时间段的交集
* 例如 人员A非工作时间【"2024-02-16 00:00:00","2024-02-29 23:59:59"】
*      人员B非工作时间【"2024-02-01 00:00:00","2024-02-19 23:59:59"】
* 交集【"2024-02-16 00:00:00","2024-02-19 23:59:59"】
*/
public static Map<String, Object> getAllIndRange(Map<String, String> map1, Map<String, String> map2){
Map<String, Object> result = new HashMap<String, Object>();
Boolean isIntersect = false;
String startTime1 = map1.get("startTime");
String endTime1 = map1.get("endTime");
String startTime2 = map2.get("startTime");
String endTime2 = map2.get("endTime");
//两个时间范围有交集
if (startTime1.compareTo(endTime2)<0 && endTime1.compareTo(startTime2)>0) {
String intersectionStartTime = startTime1.compareTo(startTime2)>0 ? startTime1 : startTime2;
String intersectionEndTime = endTime1.compareTo(endTime2)<0 ? endTime1 : endTime2;
isIntersect = true;
Map<String, String> newRange = new HashMap<String, String>();
newRange.put("startTime", intersectionStartTime);
newRange.put("endTime", intersectionEndTime);
result.put("result", newRange);
}
result.put("isIntersect", isIntersect);
return result;
}
//    二、交集:查询时间区间内【所有人】工作的时间区间
/* 第一步:每个人员在查询时间区间内的工作时间
* 第二步:循环取交集,没有立刻返回空
* 结果:无
*/
public static Map<String, String> getIntersection(String beginTime, String endTime, List<Map<String,String>> inMainList) {
//第一步:每个人员在查询时间区间内的工作时间
List<Map<String, String>> inIntersectionList = findSingleIn(beginTime, endTime, inMainList);
//第二步:循环两两取交集,没有立刻返回空
Map<String, String> allInMap = new HashMap<>();
for(int i = 0; i < inIntersectionList.size(); i++){
Map<String, String> inIntersectionMap = inIntersectionList.get(i);
if(i == 0){
allInMap = inIntersectionMap;
}else{
//两两取交集
Map<String, Object> result = getAllIndRange(inIntersectionMap, allInMap);
if ((Boolean) result.get("isIntersect")) {//有交集存起来,存储新的
allInMap = (Map<String, String>) result.get("result");
}else{
return null;//无交集返回空
}
}
}
return allInMap;
}

/* 每个人员在查询时间区间内的工作时间
*人员A工作时间【"2024-02-01 00:00:00","2024-02-15 23:59:59"】
*人员B工作时间【"2024-02-20 00:00:00","2024-02-29 23:59:59"】
*人员C工作时间【"2024-02-10 00:00:00","2024-02-15 23:59:59"】
**/
public static List<Map<String, String>> findSingleIn(String beginTime, String endTime, List<Map<String,String>> inMainList){
List<Map<String, String>> inIntersectionList = new ArrayList<>();
Map<String, String> rangeMap = new HashMap<>();
rangeMap.put("startTime",beginTime);
rangeMap.put("endTime",endTime);
for(Map<String,String> inMap : inMainList) {
Map<String, Object> intersectionMap = getAllIndRange(rangeMap, inMap);
Boolean isIntersect = (Boolean) intersectionMap.get("isIntersect");
if(isIntersect) {
inIntersectionList.add((Map<String, String>) intersectionMap.get("result"));
}
}
return inIntersectionList;
}
// 三、并集:查询时间区间内【有人】工作的时间区间
/* 第一步:每个人员在查询时间区间内的工作时间
* 第二步:循环合并起来
* 结果:【"2024-02-01 00:00:00","2024-02-15 23:59:59"】【"2024-02-20 00:00:00","2024-02-29 23:59:59"】
* */
public static List<Map<String, String>> getDateTimeUninon(String beginTime, String endTime, List<Map<String,String>> inMainList) {
//第一步:每个人员在查询时间区间内的工作时间
List<Map<String, String>> inIntersectionList = findSingleIn(beginTime, endTime, inMainList);
//第二步:循环合并起来
List<Map<String, String>> inList = new ArrayList<Map<String, String>>();
for(int i = 0; i < inIntersectionList.size(); i++) {
Map<String, String> inIntersectionMap = inIntersectionList.get(i);
if(i == 0){
inList.add(inIntersectionMap);
}else {
List<Map<String, String>> newInList = new ArrayList<Map<String, String>>();//临时存存新的
//两个时间段 [S1, E1]、[S2, E2],S2 < E1 && S1 < E2 则有交集,取并集存储;否则直接存储
for(int j = 0; j< inList.size(); j++) {
Map<String, String> inMap = inList.get(j);
if (inMap.get("startTime").compareTo(inIntersectionMap.get("endTime")) < 0 && inMap.get("endTime").compareTo(inIntersectionMap.get("startTime")) > 0) {
inIntersectionMap.put("startTime", getExtremumDate(false, inMap.get("startTime"), inIntersectionMap.get("startTime")));
inIntersectionMap.put("endTime", getExtremumDate(true, inMap.get("endTime"), inIntersectionMap.get("endTime")));
} else {
newInList.add(inMap);
}
if(j == inList.size()-1) {
newInList.add(inIntersectionMap);
}
}
inList = newInList;
}
}
return inList;
}

/**
* 获取日期中的最大或最小者
* @param maxOrMin true 最大值 false最小值
* @return 最大或最小的日期
*/
public static String getExtremumDate(Boolean maxOrMin, String time1, String time2){
if (maxOrMin){
return time1.compareTo(time2)>0? time1:time2;
}else {
return time1.compareTo(time2)>0? time2:time1;
}
}
posted @ 2024-02-20 10:31  爱吐泡泡的小小鱼  阅读(69)  评论(0编辑  收藏  举报