一、需求场景
    计划表中存在个人计划,轮换计划,查询出来的数据是一条一条的记录,个人计划的时间范围可能与轮换计划时间有交叉,需要根据个人计划的数据,将有时间交叉的轮换计划进行拆分,拆成多条记录显示。
原数据界面显示
需要处理成
二、实现思路
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;
	}


    
发表评论