项目中要去对多时段合并去重
例如:
2020/05/05-2020/05/09的08:00-9:30
2020/05/06-2020/05/12的08:30-12:30
2020/05/10-2020/05/17的11:00-14:00
合并去重完之后:
2020/06/05 08:00-9:30
2020/06/06-2020/06/09 08:00-12:30
2020/06/10-2020/06/12 08:30-14:00
2020/06/13-2020/06/17 11:00-14:00
package com.key.win.vo;
public class MyTime implements Comparable<MyTime> {
private int start;
private int end;
public MyTime(int start, int end) {
super();
this.start = start;
this.end = end;
}
public MyTime() {
}
public int getStart() {
return start;
}
public int getEnd() {
return end;
}
public int compareTo(MyTime other) {
if (start == other.start) {
return other.end - end;
}
return start - other.start;
}
public void setStart(int start) {
this.start = start;
}
public void setEnd(int end) {
this.end = end;
}
}
package com.key.win.vo;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
public class TimeVo {
private List<Date> dates = new ArrayList<Date>();
private List<String> dateStrs = new ArrayList<String>();
private List<String> specialPeriods = new ArrayList<String>();
public List<Date> getDates() {
return dates;
}
public void setDates(List<Date> dates) {
this.dates = dates;
}
public List<String> getSpecialPeriods() {
return specialPeriods;
}
public void setSpecialPeriods(List<String> specialPeriods) {
this.specialPeriods = specialPeriods;
}
public List<String> getDateStrs() {
return dateStrs;
}
public void setDateStrs(List<String> dateStrs) {
this.dateStrs = dateStrs;
}
public void addDate(Date date) {
this.dates.add(date);
}
public void addSpecialPeriod(String specialPeriod) {
this.specialPeriods.add(specialPeriod);
}
public void addDate(String date) {
this.dateStrs.add(date);
}
}
package com.key.win.dgt;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Stack;
import java.util.TreeSet;
import com.key.win.utils.DateUtils;
import com.key.win.vo.MyTime;
import com.key.win.vo.TimeVo;
public class TimeCallTest {
public static void main(String[] args) throws Exception {
List<TimeVo> times = new ArrayList<TimeVo>();
TimeVo timeVo1 = new TimeVo();
times.add(timeVo1);
//5- 9
createTime(0, 4, timeVo1);
timeVo1.addSpecialPeriod("08:00-9:30");
TimeVo timeVo2 = new TimeVo();
times.add(timeVo2);
//6-12
createTime(1, 7, timeVo2);
timeVo2.addSpecialPeriod("08:30-12:30");
//timeVo2.addSpecialPeriod("15:30-19:30");
TimeVo timeVo3 = new TimeVo();
times.add(timeVo3);
//10-17
createTime(5, 12, timeVo3);
timeVo3.addSpecialPeriod("11:00-14:00");
TimeVo timeVo4 = new TimeVo();
//times.add(timeVo4);
//5-15
createTime(0, 10, timeVo4);
System.out.println("-----------------------------end--------------------");
Map<String, Set<String>> days = TimeCallTest.splitDateTime(times);
Map<String, Set<String>> everyDays = TimeCallTest.getEveryDay(days);
Map<String, Set<String>> sortedMap = TimeCallTest.sortHashMap(everyDays);
List<TimeVo> outTimes = TimeCallTest.unionDateTime(sortedMap);
System.out.println(outTimes);
}
public static String forSet(Set<String> datetimes) {
String datetimeNew = "";
if (datetimes != null && datetimes.size() > 0) {
Iterator<String> iDatetimes = datetimes.iterator();
while (iDatetimes.hasNext()) {
datetimeNew += iDatetimes.next();
}
}
return datetimeNew;
}
public static List<TimeVo> unionDateTime(Map<String, Set<String>> sortedMap) throws Exception {
// 把所有的日期放入list中
List<String> keys = new ArrayList<String>(sortedMap.keySet());
// 获取第一天的
String dateStr = keys.get(0);
// 将String 类型转化为日期类型,获取最小的第一天的
Date dateStart = DateUtils.strToDate(dateStr);
// 获取最后一个日期的
Date dateEnd = DateUtils.strToDate(keys.get(keys.size() - 1));
Calendar startCalendar = Calendar.getInstance();
startCalendar.setTime(dateStart);
startCalendar.add(startCalendar.DATE, 1);
Set<String> dateSets = new TreeSet<String>();
// 获取最小的天的时段
Set<String> times = sortedMap.get(dateStr);
// 获取的是最小的天
String dateSet = dateStr;
String tiemStrs = forSet(times);
for (; startCalendar.getTime().before(dateEnd) || startCalendar.getTime().equals(dateEnd); startCalendar.add(startCalendar.DATE, 1)) {
// 获取下一天
Date curDate = startCalendar.getTime();
// 转为String
String curDateStr = DateUtils.dateToStr(curDate);
// 不为空,说明有这一天
if (sortedMap.get(curDateStr) != null) {
// 获取时段
Set<String> curTimes = sortedMap.get(curDateStr);
// 把时段拼接起来
String curTiemStr = forSet(curTimes);
// 两个时段如果相同,说明这两天用的是同一个时段
if (curTiemStr.equals(tiemStrs) && StringUtils.isNotBlank(dateSet)) {
// 把同一个时段先标记起来
dateSet += "@" + curDateStr;
} else {
// 否则,这两天不是同一个时段,就是不同的两个,直接放入
if(StringUtils.isNotBlank(dateSet) && StringUtils.isNotBlank(tiemStrs) ){
dateSets.add(dateSet);
}
dateSet = curDateStr;
tiemStrs = curTiemStr;
}
}else{
// 否则,这两天不是同一个时段,就是不同的两个,直接放入
if(StringUtils.isNotBlank(dateSet) && StringUtils.isNotBlank(tiemStrs) )
dateSets.add(dateSet);
dateSet = "";
tiemStrs = "";
}
}
dateSets.add(dateSet);
List<TimeVo> outTimes = new ArrayList<TimeVo>();
Iterator<String> dateSetStrs = dateSets.iterator();
while (dateSetStrs.hasNext()) {
String idateStr = dateSetStrs.next();
String[] splitStrs = idateStr.split("@");
TimeVo tv = new TimeVo();
String tvStartDate = splitStrs[0];
Set<String> tvSet = sortedMap.get(tvStartDate);
tv.addDate(tvStartDate);
if (tvSet != null && tvSet.size() > 0) {
List<String> tvSps = new ArrayList<String>(tvSet);
tv.getSpecialPeriods().addAll(tvSps);
}
if (splitStrs.length > 1) {
tv.addDate(splitStrs[splitStrs.length - 1]);
}
outTimes.add(tv);
}
return outTimes;
}
public static Map<String, Set<String>> sortHashMap(Map<String, Set<String>> everyDays) {
Map<String, Set<String>> sortedMap = new LinkedHashMap<>();
List<String> list = new ArrayList<String>();
Iterator<String> item = everyDays.keySet().iterator();
while (item.hasNext()) {
list.add(item.next());
}
Collections.sort(list);
Iterator<String> item2 = list.iterator();
while (item2.hasNext()) {
String key = item2.next();
sortedMap.put(key, everyDays.get(key));
}
return sortedMap;
}
public static Map<String, Set<String>> splitDateTime(List<TimeVo> times) {
Map<String, Set<String>> allDateTime = new HashMap<String, Set<String>>();
for (int i = 0; i < times.size(); i++) {
TimeVo vo = times.get(i);
for (int j = 0; j < vo.getDates().size(); j++) {
Date date = vo.getDates().get(j);
String dateStr = DateUtils.dateToStr(date);
Set<String> dateTimes = allDateTime.get(dateStr);
if (dateTimes == null) {
dateTimes = new HashSet<String>();
allDateTime.put(dateStr, dateTimes);
}
if (vo.getSpecialPeriods() != null && vo.getSpecialPeriods().size() > 0) {
for (int m = 0; m < vo.getSpecialPeriods().size(); m++) {
String dateTime = vo.getSpecialPeriods().get(m);
//对日期做预期处理,比例不符合格式之类
dateTimes.add(dateTime);
}
} else {
allDateTime.put(dateStr, new HashSet<String>());
}
}
}
return allDateTime;
}
public static Map<String, Set<String>> getEveryDay(Map<String, Set<String>> day) throws Exception {
Map<String, Set<String>> everDay = new HashMap<>();
for (Map.Entry<String, Set<String>> entry : day.entrySet()) {
String date = entry.getKey();
Set<String> times = entry.getValue();
if (times != null && times.size() > 0) {
//如果是一个元素就说明是一个时间段,不需要合计计算
if (times.size() == 1) {
Set<String> oneTime = new TreeSet<String>();
oneTime.add(times.toArray(new String[1])[0]);
everDay.put(date, oneTime);
} else if (times.size() > 1) {
everDay.put(date, new TreeSet<String>(TimeCallTest.unionTime(times)));
}
} else {
//....
everDay.put(date, new HashSet<String>());
}
}
return everDay;
}
public static List<String> unionTime(Set<String> timeSet) throws Exception {
List<MyTime> myTimeList = new ArrayList<MyTime>();
Iterator<String> it = timeSet.iterator();
Map<Integer, String> num2Str = new HashMap<Integer, String>();
//拆分组装成MyTime格式
while (it.hasNext()) {
String str = (String) it.next();
String[] startEndTimes = str.split("-");
String startTime = startEndTimes[0];
String endTime = startEndTimes[1];
String startHM[] = startTime.split(":");
int startMin = Integer.parseInt(startHM[0]) * 60 + Integer.parseInt(startHM[1]);
num2Str.put(startMin, startTime);
String endHM[] = endTime.split(":");
int endMin = Integer.parseInt(endHM[0]) * 60 + Integer.parseInt(endHM[1]);
num2Str.put(endMin, endTime);
MyTime myTime = new MyTime(startMin, endMin);
myTimeList.add(myTime);
}
Collections.sort(myTimeList);
//System.out.println(myTimeList.size());
//开时时间
Stack<Integer> s = new Stack<Integer>();
//结束时间
Stack<Integer> e = new Stack<Integer>();
s.push(0);
e.push(0);
for (MyTime time : myTimeList) {
if (time.getStart() > time.getEnd()) {
throw new Exception("The time is incorrect.");
}
if (time.getStart() > e.peek()) //没有交集
{
s.push(time.getStart());
e.push(time.getEnd());
} else if (time.getEnd() > (int) e.peek()) //有部分交集,取并集
{
e.pop();
e.push(time.getEnd());
}
//else {} //完全被覆盖
}
List<String> dateTimes = new ArrayList<String>();
while (!s.empty()) {
String startStr = num2Str.get(s.pop());
String endStr = num2Str.get(e.pop());
if (startStr != null && !"".equals(startStr) && endStr != null && !"".equals(endStr)) {
dateTimes.add(startStr + "-" + endStr);
}
}
return dateTimes;
}
public static void createTime(int start, int end, TimeVo timeVo) {
System.out.println("createTime----------------start----------------------");
for (int i = start; i <= end; i++) {
Calendar now = Calendar.getInstance();
now.add(Calendar.DATE, i);
timeVo.addDate(now.getTime());
System.out.println("createTime----------------" + new SimpleDateFormat("yyyy-MM-dd").format(now.getTime()) + "----------------------");
}
System.out.println("createTime----------------end----------------------");
}
}