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


发表评论