多個日期時間段進行合併,算出經歷的時長

多個日期時間段進行合併,算出經歷的時長

背景描述

在公司進行人員描圖模塊開發時,涉及到了人員參會時長和參會次數的數據,比如一個人,兩個月內開了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進行遞歸,每次都會合並重復的時間段,直到不需要進行合併,結束遞歸,進行返回,這樣就可以獲取到了不重複的時間段列表,遍歷獲取每個時間段的開始和結束時間,進行計算即可。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章