一、需求场景
计划表中存在个人计划,轮换计划,查询出来的数据是一条一条的记录,个人计划的时间范围可能与轮换计划时间有交叉,需要根据个人计划的数据,将有时间交叉的轮换计划进行拆分,拆成多条记录显示。
原数据界面显示
需要处理成
二、实现思路
1、获取全部数据,按类型进行分类,轮换计划集合,个人计划集合。
2、处理数据,根据某轮换计划的起始时间,获取该时间范围内有交叉的个人计划集合。
3、遍历全部轮换计划,处理参数调用递归方法获取拆分后的轮换计划集合。
4、将全部的拆分后的轮换计划集合以及全部的个人计划集合合并,得到返回结果集。
三、递归算法
算法思路:
以轮换计划的 字符串 "开始日期-结束日期" 为元素的集合 为参数1,以该时间段内的个人计划集合为参数2 元素为字符串 "开始日期-结束日期" 进行运算。循环轮换计划集合元素,根据个人计划的开始日期,结束日期,与当前轮换计划的开始日期,结束日期比较。完全包含在范围内的个人计划,将轮换计划拆分为两段,只有一个日期在其中的,将轮换计划拆分为一段,不在其中的,直接返回原结果。每匹配一项个人计划,轮换计划的集合元素可能会增加,个人计划集合中的元素会减少一项。直到个人计划集合中没有元素,结束递归方法。
算法实现:
/** * * <p>根据时间段将List中的时间段进行拆分 * @param timeList * @param timeStr * @return * @return List<String> * author: zhengjianhua * @throws Exception */ public List<String> getTimeStringList(List<String> timeList,List<String> curtimeList) throws Exception{ //返回结果 List<String> result=new ArrayList<String>(); //判断个人计划时间段list不为空 if(CollectionUtils.isNotEmpty(curtimeList)){ //取第一项做处理 String curtimeStr=curtimeList.get(0); //删除第一项内容 curtimeList.remove(0); //当前项开始时间 String curStartTime=curtimeStr.split("_")[0]; //当前项结束时间 String curEndTime=curtimeStr.split("_")[1]; //判断轮换计划时间段list不为空 if(CollectionUtils.isNotEmpty(timeList)){ //遍历 for (String time : timeList) { //开始时间 String startTime=time.split("_")[0]; //结束时间 String endTime=time.split("_")[1]; //当前项开始时间大于开始时间,当前项结束时间小于结束时间 if(DateUtils.dateCompare(curStartTime,startTime,DateUtils.DATE_FULL_STR)>0 && DateUtils.dateCompare(curEndTime,endTime,DateUtils.DATE_FULL_STR)<0 ){ //取两个值,一个是开始时间到 当前开始时间-1天 result.add(startTime+"_"+DateUtils.getDateByNresultString(curStartTime, 1)+" 00:00:00"); //一个是当前结束时间+1天 到 结束时间 result.add(DateUtils.getDateByNresultString(curEndTime, -1)+" 00:00:00"+"_"+endTime); //当前项开始时间大于开始时间 并且当前项开始时间 小于等于结束时间 }else if(DateUtils.dateCompare(curStartTime,startTime,DateUtils.DATE_FULL_STR)>0 && DateUtils.dateCompare(curStartTime,endTime,DateUtils.DATE_FULL_STR)<=0 ){ //取一个值 开始时间到 当前开始时间-1天 result.add(startTime+"_"+DateUtils.getDateByNresultString(curStartTime, 1)+" 00:00:00"); //当前项结束时间小于结束时间 并且当前项结束时间 大于等于开始时间 }else if(DateUtils.dateCompare(curEndTime,endTime,DateUtils.DATE_FULL_STR)<0 && DateUtils.dateCompare(curEndTime,startTime,DateUtils.DATE_FULL_STR)>=0 ){ //取一个值 当前结束时间+1天 到 结束时间 result.add(DateUtils.getDateByNresultString(curEndTime, -1)+" 00:00:00"+"_"+endTime); }else{ //没有匹配的,将原始值返回到集合中 result.add(time); } } } result=getTimeStringList(result, curtimeList); return result; }else{ result=timeList; return result; } }
工具类附件:DateUtils.txt
测试方法:
public static void main(String[] args) { List<String> list1=new ArrayList<String>(); list1.add("2018-12-25 00:00:00_2019-01-17 00:00:00"); List<String> list2=new ArrayList<String>(); list2.add("2018-12-26 00:00:00_2019-01-01 00:00:00"); list2.add("2019-01-03 00:00:00_2019-01-05 00:00:00"); list2.add("2019-01-15 00:00:00_2019-01-20 00:00:00"); try { List<String> list3=getTimeStringList(list1, list2); System.out.println(list3); } catch (Exception e) { e.printStackTrace(); } }
返回结果:
[2018-12-25 00:00:00_2018-12-25 00:00:00, 2019-01-02 00:00:00_2019-01-02 00:00:00, 2019-01-06 00:00:00_2019-01-14 00:00:00]
四、需求实现
/** * * <p>排序和拆分数据 * @param rotationList * @return * @return List<Map<String,Object>> * author: zhengjianhua * @throws Exception */ public List<Map<String, Object>> sortAndBreakUp(List<Map<String, Object>> rotationList) throws Exception{ /** * 1、获取数据,获取全部轮换计划List1 获取全部个人计划List2 * 2、分析数据,依据轮换计划中最小的开始日期,和最大的结束日期,获取该时间段内全部的个人计划List3。 * 3、创建最终返回数据List * 4、处理数据,调用递归方法 */ //结果集合数据 List<Map<String,Object>> resultList=new ArrayList<Map<String,Object>>(); //全部轮换计划 List<Map<String,Object>> allRotationPlanList=new ArrayList<Map<String,Object>>(); //全部个人计划 List<Map<String,Object>> allPersonPlanList=new ArrayList<Map<String,Object>>(); //遍历数据集合 if(CollectionUtils.isNotEmpty(rotationList)){ for (Map<String, Object> map : rotationList) { //计划类型 1轮换计划 2个人计划 String plan_type=map.get("plan_type")==null?"1":String.valueOf(map.get("plan_type")); if("1".equals(plan_type)){ allRotationPlanList.add(map); }else{ allPersonPlanList.add(map); } } } //轮换计划排序 Collections.sort(allRotationPlanList, new Comparator<Map<String, Object>>() { @Override public int compare(Map<String, Object> o1, Map<String, Object> o2) { return DateUtils.dateCompare(o1.get("starttime").toString(),o2.get("starttime").toString(),DateUtils.DATE_FULL_STR); } }); //遍历轮换计划 if(CollectionUtils.isNotEmpty(allRotationPlanList)){ for (Map<String, Object> map : allRotationPlanList) { //临时轮换计划集合 List<Map<String, Object>> tempRotationList=new ArrayList<Map<String, Object>>(); //轮换计划开始时间 String minStartTime=map.get("starttime")==null?"":String.valueOf(map.get("starttime")); //轮换计划结束时间 String maxEndTime=map.get("endtime")==null?"":String.valueOf(map.get("endtime")); //当前时间段内个人计划 List<Map<String,Object>> curPersonPlanList=getTimeQuanTumPlanList(allPersonPlanList, minStartTime, maxEndTime); //创建临时集合 List<String> timeList=new ArrayList<String>(); //最大范围时间区间 timeList.add(minStartTime+"_"+maxEndTime); //个人计划时间范围区间集合 List<String> curtimeList=new ArrayList<String>(); //遍历当前时段内个人计划 if(CollectionUtils.isNotEmpty(curPersonPlanList)){ for (Map<String, Object> map2 : curPersonPlanList) { //个人计划开始时间 String minStartTime1=map2.get("starttime")==null?"":String.valueOf(map2.get("starttime")); //个人计划结束时间 String maxEndTime1=map2.get("endtime")==null?"":String.valueOf(map2.get("endtime")); //个人计划时间范围 String timeStr=minStartTime1+"_"+maxEndTime1; //添加进集合 curtimeList.add(timeStr); } } //调用递归方法,获取该时间段内,被分割之后的轮换计划的时间范围 List<String> tempResult=getTimeStringList(timeList, curtimeList); //判断不为空 if(CollectionUtils.isNotEmpty(tempResult)){ //遍历生成轮换计划数据集合 for (String string : tempResult) { String starttime=string.split("_")[0]; String endtime=string.split("_")[1]; //生成新的map对象 Map<String, Object> tempMap=new HashMap<String,Object>(); //给map赋值 tempMap.putAll(map); //设置开始时间,结束时间 tempMap.put("starttime", starttime); tempMap.put("STARTTIME", starttime); tempMap.put("endtime", endtime); tempMap.put("ENDTIME", endtime); //添加元素到集合 tempRotationList.add(tempMap); } } //将集合添加到结果集中 resultList.addAll(tempRotationList); } } //再将个人计划添加到结果集中 resultList.addAll(allPersonPlanList); //对结果集进行排序 Collections.sort(resultList, new Comparator<Map<String, Object>>() { @Override public int compare(Map<String, Object> o1, Map<String, Object> o2) { return DateUtils.dateCompare(o1.get("starttime").toString(),o2.get("starttime").toString(),DateUtils.DATE_FULL_STR); } }); //处理状态 for (Map<String, Object> map3 : resultList) { //开始时间 String starttime=map3.get("starttime")==null?"":String.valueOf(map3.get("starttime")); //结束时间 String endtime=map3.get("endtime")==null?"":String.valueOf(map3.get("endtime")); //当前时间 String nowtime=DateUtils.getNowTime(); //当前状态 String curstate=""; //第一种情况 当前时间大于开始时间(00:00:00) 当前时间带时分秒;当前时间小于结束时间(00:00:00)+1天 if( DateUtils.dateCompare(nowtime, starttime, DateUtils.DATE_FULL_STR)>0 && DateUtils.dateCompare(nowtime, DateUtils.nextDate(endtime, DateUtils.DATE_FULL_STR), DateUtils.DATE_FULL_STR)<0 ){ //实习中 curstate="1"; //第二种情况 当前时间小于开始时间(00:00:00) }else if( DateUtils.dateCompare(nowtime, starttime, DateUtils.DATE_FULL_STR)<0 ){ //未开始 curstate="0"; //第三种情况 当前时间大于结束时间+1天 }else if( DateUtils.dateCompare(nowtime, DateUtils.nextDate(endtime, DateUtils.DATE_FULL_STR), DateUtils.DATE_FULL_STR)>0 ){ //已结束 curstate="2"; } map3.put("curstate", curstate); } //返回结果集 return resultList; } /** * * <p>根据时间段将List中的时间段进行拆分 * @param timeList * @param timeStr * @return * @return List<String> * author: zhengjianhua * @throws Exception */ public List<String> getTimeStringList(List<String> timeList,List<String> curtimeList) throws Exception{ //返回结果 List<String> result=new ArrayList<String>(); //判断个人计划时间段list不为空 if(CollectionUtils.isNotEmpty(curtimeList)){ //取第一项做处理 String curtimeStr=curtimeList.get(0); //删除第一项内容 curtimeList.remove(0); //当前项开始时间 String curStartTime=curtimeStr.split("_")[0]; //当前项结束时间 String curEndTime=curtimeStr.split("_")[1]; //判断轮换计划时间段list不为空 if(CollectionUtils.isNotEmpty(timeList)){ //遍历 for (String time : timeList) { //开始时间 String startTime=time.split("_")[0]; //结束时间 String endTime=time.split("_")[1]; //当前项开始时间大于开始时间,当前项结束时间小于结束时间 if(DateUtils.dateCompare(curStartTime,startTime,DateUtils.DATE_FULL_STR)>0 && DateUtils.dateCompare(curEndTime,endTime,DateUtils.DATE_FULL_STR)<0 ){ //取两个值,一个是开始时间到 当前开始时间-1天 result.add(startTime+"_"+DateUtils.getDateByNresultString(curStartTime, 1)+" 00:00:00"); //一个是当前结束时间+1天 到 结束时间 result.add(DateUtils.getDateByNresultString(curEndTime, -1)+" 00:00:00"+"_"+endTime); //当前项开始时间大于开始时间 并且当前项开始时间 小于等于结束时间 }else if(DateUtils.dateCompare(curStartTime,startTime,DateUtils.DATE_FULL_STR)>0 && DateUtils.dateCompare(curStartTime,endTime,DateUtils.DATE_FULL_STR)<=0 ){ //取一个值 开始时间到 当前开始时间-1天 result.add(startTime+"_"+DateUtils.getDateByNresultString(curStartTime, 1)+" 00:00:00"); //当前项结束时间小于结束时间 并且当前项结束时间 大于等于开始时间 }else if(DateUtils.dateCompare(curEndTime,endTime,DateUtils.DATE_FULL_STR)<0 && DateUtils.dateCompare(curEndTime,startTime,DateUtils.DATE_FULL_STR)>=0 ){ //取一个值 当前结束时间+1天 到 结束时间 result.add(DateUtils.getDateByNresultString(curEndTime, -1)+" 00:00:00"+"_"+endTime); }else{ //没有匹配的,将原始值返回到集合中 result.add(time); } } } result=getTimeStringList(result, curtimeList); return result; }else{ result=timeList; return result; } } /** * * <p>获取指定时间段内的个人计划集合 * @param planList * @param minStartTime * @param maxEndTime * @return * @return List<Map<String,Object>> * author: zhengjianhua */ public List<Map<String, Object>> getTimeQuanTumPlanList(List<Map<String, Object>> planList,String minStartTime,String maxEndTime){ //临时集合 List<Map<String, Object>> tempList=new ArrayList<Map<String, Object>>(); if(CollectionUtils.isNotEmpty(planList)){ for (Map<String, Object> map : planList) { //个人计划开始时间 String starttime=map.get("starttime")==null?"":String.valueOf(map.get("starttime")); //个人计划结束时间 String endtime=map.get("endtime")==null?"":String.valueOf(map.get("endtime")); //时间不为空 if(StringUtils.isNotEmpty(minStartTime) && StringUtils.isNotEmpty(maxEndTime)) { //个人计划开始时间在范围内 或者个人计划结束时间在范围内 包含边界值 if((DateUtils.dateCompare(starttime,minStartTime,DateUtils.DATE_FULL_STR)>=0 && DateUtils.dateCompare(starttime,maxEndTime,DateUtils.DATE_FULL_STR)<=0) || (DateUtils.dateCompare(endtime,minStartTime,DateUtils.DATE_FULL_STR)>=0 && DateUtils.dateCompare(endtime,maxEndTime,DateUtils.DATE_FULL_STR)<=0) ){ //添加到时间段个人计划集合中 tempList.add(map); } } } } return tempList; }
发表评论