工作中遇到这种需求了,就写了一个方法,测试了几种情况都没有问题
代码中的工具类用的hutool
public void timeTest() {
//原时间段集合
List<Map<String, Date>> list = new ArrayList<Map<String, Date>>() {
{
Map<String, Date> m = new HashMap<>();
m.put("st", DateUtil.parse("2021-09-30"));
m.put("et", DateUtil.parse("2021-10-08"));
add(m);
Map<String, Date> m2 = new HashMap<>();
m2.put("st", DateUtil.parse("2021-10-08"));
m2.put("et", DateUtil.parse("2021-10-12"));
add(m2);
Map<String, Date> m3 = new HashMap<>();
m3.put("st", DateUtil.parse("2021-10-12"));
m3.put("et", DateUtil.parse("2021-10-12"));
add(m3);
}};
List<Map<String, Date>> resultList = new ArrayList<>();
//处理节假日
list.forEach(m -> resultList.addAll(this.dispose(m)));
resultList.forEach(map -> System.out.println(map.values()));
}
/**
* 处理单个时间段中的节假日
*
* @param m 时间段
* @return 处理过后的一个或多个时间段
*/
public List<Map<String, Date>> dispose(Map<String, Date> m) {
String ymd = "yyyy-MM-dd";
//节假日,正常来说应该每年的节假日维护在数据库中
List<String> holidays = new ArrayList<String>() {
{
add("2021-10-01");
add("2021-10-02");
add("2021-10-03");
add("2021-10-04");
add("2021-10-05");
add("2021-10-06");
add("2021-10-07");
}};
//法定工作日,也维护在数据库中
List<String> workDays = new ArrayList<String>() {
{
add("2021-09-26");
add("2021-10-09");
}};
Date st = m.get("st");
Date et = m.get("et");
List<Map<String, Date>> result = new ArrayList<>();
long betweenDay = DateUtil.betweenDay(st, et, true) + 1;
for (int i = 0; i < betweenDay; i++) {
if (st.compareTo(et) > 0) {
break;
} else if (st.compareTo(et) == 0) {
String last = DateUtil.format(st, ymd);
if (workDays.contains(last) || (!holidays.contains(last) && !DateTime.of(st).isWeekend())) {
Map<String, Date> map = new HashMap<>();
map.put("st", st);
map.put("et", et);
result.add(map);
}
break;
}
if (holidays.contains(DateUtil.format(st, ymd))) {
st = DateUtil.offsetDay(st, 1);
} else if (workDays.contains(DateUtil.format(st, ymd))) {
Date beginT = st;
Date endT = st;
long betweenDay1 = DateUtil.betweenDay(st, et, true) + 2;
for (int j = 0; j < betweenDay1; j++) {
st = DateUtil.offsetDay(st, 1);
if (holidays.contains(DateUtil.format(st, ymd))) {
Map<String, Date> map = new HashMap<>();
map.put("st", beginT);
map.put("et", endT);
result.add(map);
break;
} else if (workDays.contains(DateUtil.format(st, ymd))) {
endT = st;
} else {
if (DateTime.of(st).isWeekend()) {
Map<String, Date> map = new HashMap<>();
map.put("st", beginT);
map.put("et", endT);
result.add(map);
break;
} else {
if (st.compareTo(et) > 0) {
Map<String, Date> map = new HashMap<>();
DateTime zt = DateUtil.offsetDay(st, -1);
map.put("st", beginT);
map.put("et", zt);
result.add(map);
break;
}
endT = st;
}
}
}
st = DateUtil.offsetDay(endT, 2);
} else {
if (DateTime.of(st).isWeekend()) {
st = DateUtil.offsetDay(st, 1);
} else {
Date beginT = st;
Date endT = st;
long betweenDay1 = DateUtil.betweenDay(st, et, true) + 2;
for (int j = 0; j < betweenDay1; j++) {
st = DateUtil.offsetDay(st, 1);
if (holidays.contains(DateUtil.format(st, ymd))) {
Map<String, Date> map = new HashMap<>();
map.put("st", beginT);
map.put("et", endT);
result.add(map);
break;
} else if (workDays.contains(DateUtil.format(st, ymd))) {
endT = st;
} else {
if (DateTime.of(st).isWeekend()) {
Map<String, Date> map = new HashMap<>();
map.put("st", beginT);
map.put("et", endT);
result.add(map);
break;
} else {
if (st.compareTo(et) > 0) {
Map<String, Date> map = new HashMap<>();
DateTime zt = DateUtil.offsetDay(st, -1);
map.put("st", beginT);
map.put("et", zt);
result.add(map);
break;
}
endT = st;
}
}
}
st = DateUtil.offsetDay(endT, 2);
}
}
}
return result;
}
输出结果:
还有一个计算多个时间段中重复天数的方法,有需要可以看这里:java 计算多个时间段中重复的天数