多个日期时间段进行合并,算出经历的时长

2 篇文章 0 订阅
1 篇文章 0 订阅

多个日期时间段进行合并,算出经历的时长

背景描述

在公司进行人员描图模块开发时,涉及到了人员参会时长和参会次数的数据,比如一个人,两个月内开了14次会议。这里面就涉及到了,如果这个人参加的两个甚至多个会议有重叠的部分,这样的时间如何通过程序去进行合并处理。

思路

我们在程序中,可以将多个时间段中的两段分别“冒泡”比较,如果有重叠,那么进行合并,将这两个段去除,将合并后的时间段加入,得到的新的时间段的列表,重复上面的过程,直到没有重叠的时间段为止(递归

代码示例

  1. 定义一个类,类中有两个方法,getOverlapTimegetTimeBucketList

方法getOverlapTime:

public void getOverlapTime() throws ParseException {
		DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		
		List<TimeBucket> timeBucketList = new ArrayList<TimeBucket>();
		timeBucketList.add(new TimeBucket("2019-10-29 13:30:00", "2019-10-29 16:30:00"));
		timeBucketList.add(new TimeBucket("2019-10-29 13:30:00", "2019-10-29 17:30:00"));
		timeBucketList.add(new TimeBucket("2019-10-30 14:30:00", "2019-10-30 17:30:00"));
		timeBucketList.add(new TimeBucket("2019-10-30 15:30:00", "2019-10-30 18:30:00"));
		timeBucketList.add(new TimeBucket("2019-10-30 16:30:00", "2019-10-30 19:30:00"));
		
		List<TimeBucket> timeBucketList2 = getTimeBucketList(timeBucketList);
		for (TimeBucket timeBucket : timeBucketList2) {
			String format = dateFormat.format(timeBucket.getStart());
			String format2 = dateFormat.format(timeBucket.getEnd());
			System.out.println(format+"    "+format2);
		}
		
	}

方法getTimeBucketList:

public List<TimeBucket> getTimeBucketList(List<TimeBucket> timeBucketList ) throws ParseException{
		List<TimeBucket> myTimeBucketList = timeBucketList;
		DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		
		Map<String, Integer> union = TimeBucket.union(myTimeBucketList);
		
		if(union!=null) {
			Integer i = union.get("i");
			Integer j = union.get("j");
			String start = null;
			String end = null;
			if(i.intValue()==j.intValue()) {//这条记录是多余的
				TimeBucket timeBucket = myTimeBucketList.get(i);
				myTimeBucketList.remove(timeBucket);
			}else {
				TimeBucket timeBucket = myTimeBucketList.get(i);
				String startTime1 = dateFormat.format(timeBucket.getStart());
				String endTime1 = dateFormat.format(timeBucket.getEnd());
				
				TimeBucket timeBucket2 = myTimeBucketList.get(j);
				String startTime2 = dateFormat.format(timeBucket2.getStart());
				String endTime2 = dateFormat.format(timeBucket2.getEnd());
				
				if(startTime1.compareTo(startTime2)<=0) {
					start = startTime1;
				}else {
					start = startTime2;
				}
				
				if(endTime1.compareTo(endTime2)>=0) {
					end = endTime1;
				}else {
					end = endTime2;
				}
				TimeBucket bucket = new TimeBucket(start,end);
				myTimeBucketList.remove(timeBucket);
				myTimeBucketList.remove(timeBucket2);
				myTimeBucketList.add(bucket);
			}
			getTimeBucketList(myTimeBucketList);
		}	
		return myTimeBucketList;
	}
  1. getTimeBucketList方法接收的是一个时间段列表,返回的是一个不存在重复时间段的时间段列表,这里最关键的是TimeBucket类,这里有找出哪个重复的时间段,在myTimeBucketList里的角标
public class TimeBucket {

	private static final ThreadLocal<DateFormat> FORMATS = ThreadLocal.withInitial(() -> new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));

    private final Date start;

    private final Date end;

    public TimeBucket(Date start, Date end) {
        if (start.after(end)) {
            throw new IllegalArgumentException("时间段无效(开始日期需要小于结束日期)");
        }
        this.start = start;
        this.end = end;
    }

    public TimeBucket(String start, String end) throws ParseException {
        this(parse(start), parse(end));
    }

    public TimeBucket(long startTime, long endTime) {
        this(new Date(startTime), new Date(endTime));
    }

    /**
     * TimeBucket会返回重叠的时间段
     * 若返回null说明没有重叠的时间段
     *
     * @param buckets 时间段
     * @return
     */
    public static Map<String, Integer> union(List<TimeBucket> buckets) {
    	
    	List<Map<String, String>> list = new ArrayList<Map<String,String>>();
    	
    	DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    	
        //长度为1无需判断
        if (buckets == null || buckets.size() <= 1) {
            return null;
        }
        for (int i = 0; i < buckets.size() - 1; i++) {
            String start = dateFormat.format(buckets.get(i).getStart());
            String tempStart = start;
            String end = dateFormat.format(buckets.get(i).getEnd());
            String tempEnd = end;
            for (int j = i + 1; j < buckets.size(); j++) {
            	
            	String start2 = dateFormat.format(buckets.get(j).getStart());
            	String end2 = dateFormat.format(buckets.get(j).getEnd());
            	
                if (start.compareTo(start2)<0) {
                    start = start2;
                }
                if (end.compareTo(end2)>0) {
                    end = end2;
                }
                if (start.compareTo(end)<0) {
               	
                	Map<String, Integer> map = new HashMap<String, Integer>();
                	map.put("i", i);
                	map.put("j", j);
                	return map;
                }else {
                	start = tempStart;
                	end = tempEnd;
                }
            }
        }
        return null;
    }

    public Date getStart() {
        return start;
    }

    public Date getEnd() {
        return end;
    }

    public long getStartTime() {
        return start.getTime();
    }

    public long getEndTime() {
        return end.getTime();
    }

    private static Date parse(String str) throws ParseException {
        return FORMATS.get().parse(str);
    }

    private static String format(Date str) {
        return FORMATS.get().format(str);
    }

    @Override
    public String toString() {
        return MoreObjects.toStringHelper(this)
                .add("start", format(start))
                .add("end", format(end))
                .toString();
    }
}

对getTimeBucketList进行递归,每次都会合并重复的时间段,直到不需要进行合并,结束递归,进行返回,这样就可以获取到了不重复的时间段列表,遍历获取每个时间段的开始和结束时间,进行计算即可。

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
您好!针对您的问题,我可以给您提供一些思路和代码实现。 首先,对于合并重叠时间段的问题,可以使用以下思路: 1. 将时间段按照起始时间排序; 2. 遍历时间段,如果当前时间段与前一个时间段重叠,则将其合并为一个时间段,否则将当前时间段添加到结果列表中。 具体实现可以参考以下代码: ```csharp public static List<(DateTime start, DateTime end)> MergeOverlapIntervals(List<(DateTime start, DateTime end)> intervals) { // 将时间段按照起始时间排序 intervals = intervals.OrderBy(x => x.start).ToList(); var mergedIntervals = new List<(DateTime start, DateTime end)>(); var currentInterval = intervals[0]; for (int i = 1; i < intervals.Count; i++) { var interval = intervals[i]; // 如果当前时间段与前一个时间段重叠,则将其合并为一个时间段 if (currentInterval.end >= interval.start) { currentInterval = (currentInterval.start, interval.end); } else { // 否则将当前时间段添加到结果列表中 mergedIntervals.Add(currentInterval); currentInterval = interval; } } // 添加最后一个时间段 mergedIntervals.Add(currentInterval); return mergedIntervals; } ``` 接下来,对于重叠日期按照优先级合并的问题,可以使用以下思路: 1. 将时间段按照起始时间排序; 2. 遍历时间段,如果当前时间段与前一个时间段重叠并且优先级高于前一个时间段,则将其合并为一个时间段,否则将当前时间段添加到结果列表中。 具体实现可以参考以下代码: ```csharp public static List<(DateTime start, DateTime end, int priority)> MergeOverlapIntervalsWithPriority(List<(DateTime start, DateTime end, int priority)> intervals) { // 将时间段按照起始时间排序 intervals = intervals.OrderBy(x => x.start).ToList(); var mergedIntervals = new List<(DateTime start, DateTime end, int priority)>(); var currentInterval = intervals[0]; for (int i = 1; i < intervals.Count; i++) { var interval = intervals[i]; // 如果当前时间段与前一个时间段重叠并且优先级高于前一个时间段,则将其合并为一个时间段 if (currentInterval.end >= interval.start && currentInterval.priority <= interval.priority) { currentInterval = (currentInterval.start, interval.end, interval.priority); } else { // 否则将当前时间段添加到结果列表中 mergedIntervals.Add(currentInterval); currentInterval = interval; } } // 添加最后一个时间段 mergedIntervals.Add(currentInterval); return mergedIntervals; } ``` 希望以上代码可以对您有所帮助!如果您还有其他问题,欢迎继续提问。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值