日期求差集、并集、交集
package com.xf.tools; import java.time.LocalDateTime; import java.time.LocalTime; import java.time.ZoneId; import java.util.ArrayList; import java.util.Date; import java.util.List; import cn.hutool.core.date.DateUtil; /** * 包含开始日期和结束日期的对象 */ public class DateObject { private Date startDate; private Date endDate; public DateObject(Date startDate, Date endDate) { this.startDate = startDate; this.endDate = endDate; } public Date getStartDate() { return startDate; } public void setStartDate(Date startDate) { this.startDate = startDate; } public Date getEndDate() { return endDate; } public void setEndDate(Date endDate) { this.endDate = endDate; } @Override public String toString() { return "DateObject{startDate=" + startDate + ", endDate=" + endDate + "}"; } private static Date getEndTimeOfDay(Date date) { LocalDateTime localDateTime = LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault()); return Date.from(LocalDateTime.of(localDateTime.toLocalDate(), LocalTime.MAX).atZone(ZoneId.systemDefault()) .toInstant()); } /** * 获取date当天的开始日期 * * @param date 日期 * @return date当天的开始日期 */ private static Date getFirstTimeOfDay(Date date) { LocalDateTime localDateTime = LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault()); return Date.from(LocalDateTime.of(localDateTime.toLocalDate(), LocalTime.MIN).atZone(ZoneId.systemDefault()) .toInstant()); } /** * 时间区间合并 * * @param list 日期集合 * @return 合并后日期集合 */ public static List<DateObject> merge(List<DateObject> list) { if (list == null || list.size() == 0) { return new ArrayList<>(); } List<DateObject> result = new ArrayList<>(); DateObject first = list.get(0); for (int i = 1; i < list.size(); i++) { DateObject next = list.get(i); // 合并区间,时间精确到秒(差1秒则为连续) if (next.getStartDate().getTime() < first.getEndDate().getTime() || next.getStartDate().getTime() - first.getEndDate().getTime() == 1000) { first.setStartDate(new Date(Math.min(first.getStartDate().getTime(), next.getStartDate().getTime()))); first.setEndDate(new Date(Math.max(first.getEndDate().getTime(), next.getEndDate().getTime()))); } else { // 没有交集,直接添加 result.add(first); first = next; } } result.add(first); return result; } /** * 求开放时间区间与时间区间的所有交集 * * @param dateObject 日期对象 * @param list 日期列表 * @return 日期交集 */ public static List<DateObject> intersection(DateObject dateObject, List<DateObject> list) { List<DateObject> result = new ArrayList<>(); for (DateObject date : list) { // 时间区间全部在开放时间区间内:ad.startDate <= open.startDate < open.endDate <= ad.endDate // 则[open.startDate, open.endDate] 均不开放 if (date.getStartDate().getTime() <= dateObject.getStartDate().getTime() && date.getEndDate().getTime() >= dateObject.getEndDate().getTime()) { // 开放时间区间已全部占用 break; } // 时间区间全部在开放时间区间内:open.startDate <= ad.startDate < ad.endDate <= open.endDate else if (date.getStartDate().getTime() >= dateObject.getStartDate().getTime() && date.getEndDate().getTime() <= dateObject.getEndDate().getTime()) { result.add(new DateObject(date.getStartDate(), date.getEndDate())); } // 结束时间在开放时间区间内:ad.startDate <= open.startDate <= ad.endDate <= open.endDate else if (date.getStartDate().getTime() <= dateObject.getStartDate().getTime() && date.getEndDate().getTime() >= dateObject.getStartDate().getTime() && date.getEndDate().getTime() <= dateObject.getEndDate().getTime()) { result.add(new DateObject(dateObject.getStartDate(), date.getEndDate())); } // 开始时间在开放时间区间内:open.startDate <= ad.startDate <= open.endDate <= ad.endDate else if (date.getEndDate().getTime() > dateObject.getEndDate().getTime()) { result.add(new DateObject(date.getStartDate(), dateObject.getEndDate())); } } return result; } /** * 求差集 * * @param dateObject 日期对象 * @param list 日期列表 * @return 差集 */ public static List<DateObject> differences(DateObject dateObject, List<DateObject> list) { List<DateObject> result = new ArrayList<>(); DateObject first = list.get(0); if (list.size() == 1) { if (dateObject.getStartDate().getTime() < first.getStartDate().getTime()) { result.add(new DateObject(dateObject.getStartDate(), getEndTimeOfDay(DateUtil.offsetDay(first.getStartDate(), -1)))); } if (dateObject.getEndDate().getTime() - first.getEndDate().getTime() > 1000) { result.add(new DateObject(getFirstTimeOfDay(DateUtil.offsetDay(first.getEndDate(), 1)), getEndTimeOfDay(dateObject.getEndDate()))); } } else { for (int i = 1; i < list.size(); i++) { DateObject next = list.get(i); result.add(new DateObject(getFirstTimeOfDay(DateUtil.offsetDay(first.getEndDate(), 1)), getEndTimeOfDay(DateUtil.offsetDay(next.getStartDate(), -1)))); first = next; } DateObject last = list.get(list.size() - 1); if (dateObject.getEndDate().getTime() > last.getEndDate().getTime()) { result.add(new DateObject(getFirstTimeOfDay(DateUtil.offsetDay(last.getEndDate(), 1)), getEndTimeOfDay(dateObject.getEndDate()))); } } return result; } }
private List<DateObject> init() throws Exception { List<DateObject> list = new ArrayList<>(); SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); list.add(new DateObject(format.parse("2019-07-01 00:00:00"), format.parse("2019-07-10 23:59:59"))); list.add(new DateObject(format.parse("2019-07-15 00:00:00"), format.parse("2019-07-20 23:59:59"))); list.add(new DateObject(format.parse("2019-07-22 00:00:00"), format.parse("2019-07-25 23:59:59"))); list.sort(Comparator.comparing(DateObject::getStartDate)); return list; } @Test public void test1() throws Exception { SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); // 时间区间 DateObject open = new DateObject(format.parse("2019-07-01 00:00:00"), format.parse("2019-07-31 23:59:59")); // 时间区间列表合并 List<DateObject> merge = DateObject.merge(init()); System.out.println( "时间区间求并集:" + JSONUtil.toJsonStr(merge, JSONConfig.create().setDateFormat("yyyy-MM-dd HH:mm:ss"))); // 求交集 List<DateObject> intersection = DateObject.intersection(open, merge); System.out.println("时间区间求交集:" + JSONUtil.toJsonStr(intersection, JSONConfig.create().setDateFormat("yyyy-MM-dd HH:mm:ss"))); // 求差集 if (intersection.isEmpty()) { System.out.println( "该区间不可再选:" + JSONUtil.toJsonStr(open, JSONConfig.create().setDateFormat("yyyy-MM-dd HH:mm:ss"))); return; } List<DateObject> list = DateObject.differences(open, intersection); System.out.println( "时间区间求差集:" + JSONUtil.toJsonStr(list, JSONConfig.create().setDateFormat("yyyy-MM-dd HH:mm:ss"))); }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· winform 绘制太阳,地球,月球 运作规律
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
2016-04-07 基于AspectJ自定义注解