计算多段时间的重叠

package com.lihong.DDPush.pms;

import com.lihong.DDPush.mybatis.Parser;
import org.junit.Test;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * Created by lihong10 on 2017/9/28.
 */
public class TimeOverlapTest {

    public static final String YYYY_MM_DD_HH_MM_SS = "yyyy-MM-dd HH:mm:ss";

    @Test
    public void test() {
        String[] params = new String[] {
                "2017-09-28 08:00:00",
                "2017-09-28 10:00:00",
                "2017-09-28 12:00:00",
                "2017-09-28 15:00:00",
                "2017-09-28 07:00:00",
                "2017-09-28 18:00:00"
        };

        String[] params1 = new String[] {
                "2017-09-28 08:00:00",
                "2017-09-28 10:00:00",
                "2017-09-28 12:00:00",
                "2017-09-28 15:00:00"
        };

        String[] params2 = new String[] {
                "2017-09-28 07:00:00",
                "2017-09-28 18:00:00"
        };

        caculate(params, params1, params2);
    }


    @Test
    public void test01() {
        String[] params = new String[]{
                "2017-09-28 08:00:00",
                "2017-09-28 17:00:00",
                "2017-09-28 09:00:00",
                "2017-09-28 16:00:00"
        };
        String[] params1 = new String[]{
                "2017-09-28 08:00:00",
                "2017-09-28 17:00:00"
        };

        String[] params2 = new String[]{
                "2017-09-28 09:00:00",
                "2017-09-28 16:00:00"
        };
        caculate(params, params1, params2);
    }


    @Test
    public void test02() {
        String[] params = new String[]{
                "2017-09-28 08:00:00",
                "2017-09-28 10:00:00",
                "2017-09-28 09:00:00",
                "2017-09-28 12:00:00",
                "2017-09-28 11:00:00",
                "2017-09-28 13:00:00",
                "2017-09-28 12:00:00",
                "2017-09-28 15:00:00"
        };

        String[] params1 = new String[]{
                "2017-09-28 08:00:00",
                "2017-09-28 10:00:00",
                "2017-09-28 09:00:00",
                "2017-09-28 12:00:00",
                "2017-09-28 11:00:00",
                "2017-09-28 13:00:00"
        };

        String[] params2 = new String[]{
                "2017-09-28 12:00:00",
                "2017-09-28 15:00:00"
        };

        caculate(params, params1, params2);
    }


    @Test
    public void test03() {
        String[] params = new String[]{
                "2017-09-28 08:00:00",
                "2017-09-28 10:00:00",
                "2017-09-28 09:00:00",
                "2017-09-28 12:00:00",
                "2017-09-28 11:00:00",
                "2017-09-28 13:00:00",
                "2017-09-28 12:00:00",
                "2017-09-28 15:00:00",
                "2017-09-28 07:00:00",
                "2017-09-28 11:00:00"
        };

        String[] params1 = new String[]{
                "2017-09-28 08:00:00",
                "2017-09-28 10:00:00",
                "2017-09-28 09:00:00",
                "2017-09-28 12:00:00",
                "2017-09-28 11:00:00",
                "2017-09-28 13:00:00"
        };

        String[] params2 = new String[]{
                "2017-09-28 12:00:00",
                "2017-09-28 15:00:00",
                "2017-09-28 07:00:00",
                "2017-09-28 11:00:00"
        };

        caculate(params, params1, params2);
    }


    @Test
    public void test04() {
        String[] params = new String[]{
                "2017-09-28 08:00:00",
                "2017-09-28 10:00:00",
                "2017-09-28 09:00:00",
                "2017-09-28 12:00:00",
                "2017-09-28 11:00:00",
                "2017-09-28 13:00:00",
                "2017-09-28 12:00:00",
                "2017-09-28 15:00:00",
                "2017-09-28 07:00:00",
                "2017-09-28 11:00:00"
        };

        String[] params1 = new String[] {
                "2017-09-28 08:00:00",
                "2017-09-28 10:00:00",
                "2017-09-28 09:00:00",
                "2017-09-28 12:00:00",
                "2017-09-28 11:00:00",
                "2017-09-28 13:00:00"
        };

        String[] params2 = new String[]{
                "2017-09-28 12:00:00",
                "2017-09-28 15:00:00",
                "2017-09-28 07:00:00",
                "2017-09-28 11:00:00"
        };

        caculate(params, params1, params2);
    }


    /**
     * @Author: lihong10
     * @Description:
     * @param
     * @Date: 2017/9/30  14:34
     */
    @Test
    public void test05() {
        String[] params = new String[] {
                "2017-09-28 07:00:00",
                "2017-09-28 10:00:00",
                "2017-09-28 13:00:00",
                "2017-09-28 18:00:00",
                "2017-09-28 21:00:00",
                "2017-09-28 23:00:00",
                "2017-09-28 01:00:00",
                "2017-09-28 23:40:00"
        };

        String[] params1 = new String[] {
                "2017-09-28 07:00:00",
                "2017-09-28 10:00:00",
                "2017-09-28 13:00:00",
                "2017-09-28 18:00:00",
                "2017-09-28 21:00:00",
                "2017-09-28 23:40:00"
        };

        String[] params2 = new String[]{
                "2017-09-28 01:00:00",
                "2017-09-28 23:40:00"
        };

        caculateNotInHoliday(params, params1, params2);
    }



    private void caculateNotInHoliday(String[] params, String[] authTimes, String[] parkTimes) {
        List<Date> dates = getDateList(params);
        removeRepeat(dates);
        Collections.sort(dates);


        List<TimePair> pairs = new ArrayList<TimePair>();

        for (int i = 0, j = dates.size(); i < j; i++) {
            if ((i + 2) <= j) {

                System.out.println("i: " + i + ", j: " + (i + 1));
                TimePair pair = new TimePair(dates.get(i), dates.get(i + 1));
                pairs.add(pair);
                pair.caculateOverLapWithAuth(getDateList(authTimes));
                pair.caculateOverLapWithStay(getDateList(parkTimes));
                System.out.println(pair);
                System.out.println();
            }
        }


        System.out.println("===============================================================================");
        System.out.println(pairs);
        System.out.println("===============================================================================");
        List<TimePair> notInHolidayLi = new ArrayList<>();
        for (int i = 0; i < pairs.size(); i++) {
            TimePair pair = pairs.get(i);
            if (pair.notInHoliday()) {
                notInHolidayLi.add(pair);
                System.out.println(pair);
            }
        }

        System.out.println("===============================================================================");
        System.out.println(notInHolidayLi);
        System.out.println("===============================================================================");
        System.out.println(mergeContinous(notInHolidayLi));

    }


    private void caculate(String[] params, String[] authTimes, String[] parkTimes) {
        List<Date> dates = getDateList(params);
        removeRepeat(dates);
        Collections.sort(dates);


        List<TimePair> pairs = new ArrayList<TimePair>();

        for (int i = 0, j = dates.size(); i < j; i++) {
            if ((i + 2) <= j) {

                System.out.println("i: " + i + ", j: " + (i + 1));
                TimePair pair = new TimePair(dates.get(i), dates.get(i + 1));
                pairs.add(pair);
                pair.caculateOverLapWithAuth(getDateList(authTimes));
                pair.caculateOverLapWithStay(getDateList(parkTimes));
                System.out.println(pair);
                System.out.println();
            }
        }


        System.out.println("===============================================================================");
        System.out.println(pairs);
        System.out.println("===============================================================================");
        List<TimePair> chargeTimes = new ArrayList<>();
        for (int i = 0; i < pairs.size(); i++) {
            TimePair pair = pairs.get(i);
            if (pair.needCharge()) {
                chargeTimes.add(pair);
                System.out.println(pair);
            }
        }


        System.out.println("===============================================================================");
        System.out.println("-------------------------------------------------------------------------------");
        System.out.println(chargeTimes);
        System.out.println("-------------------------------------------------------------------------------");
        System.out.println(mergeContinous(chargeTimes));

    }

    public void removeRepeat(List<Date> dates) {

        for (int i = 0; i < (dates.size() - 1); i++) {
            for (int j = i + 1; j < dates.size(); j++) {
                System.out.print("remove i: " + i);
                System.out.print("remove j: " + j);
                if (dates.get(i).getTime() == dates.get(j).getTime()) {
                    dates.remove(j);
                }
            }
        }
    }


    public List<Pair> mergeContinous(List<TimePair> pairs) {

        if (pairs == null || pairs.size() == 0) {
            return new ArrayList<Pair>();
        }

        List<Pair> li = new ArrayList<Pair>();

        if (pairs.size() == 1) {
            Pair p = new Pair(pairs.get(0).getStartTime(), pairs.get(0).getEndTime());
            li.add(p);
            return li;
        }

        Date start = pairs.get(0).getStartTime();
        Date end = pairs.get(0).getEndTime();
        for (int i = 1; i < pairs.size(); i++) {
            TimePair tp = pairs.get(i);
            if (tp.getStartTime().getTime() == end.getTime()) {
                end = tp.getEndTime();
            } else {
                Pair pr = new Pair(start, end);
                li.add(pr);

                start = tp.getStartTime();
                end = tp.getEndTime();
            }
        }

        li.add(new Pair(start, end));

        return li;
    }


    public static boolean isCollectionEmpty(Collection<?> collection) {
        if (collection == null || collection.isEmpty()) {
            return true;
        }
        return false;
    }


    public static Date stringToDate(String strValue, String strFormat) {
        Date date = null;
        try {
            date = new SimpleDateFormat(strFormat).parse(strValue);
        } catch (ParseException e) {
        }
        return date;
    }

    public static String dateToString(Date dateValue, String strFormat) {
        return new SimpleDateFormat(strFormat).format(dateValue);
    }


    public static List<Date> getDateList(String... dateStr) {

        if (dateStr == null || dateStr.length == 0) {
            return new ArrayList<>();
        }

        List<Date> result = new ArrayList<Date>();

        for (String el : dateStr) {
            result.add(stringToDate(el, YYYY_MM_DD_HH_MM_SS));
        }

        return result;
    }

    private static class TimePair {

        private Date startTime;
        private Date endTime;

        private Long startLong;
        private Long endLong;

        private String startString;
        private String endString;

        private int authOverlapCout;
        private int stayOverlapCount;


        private static final Predicate<TimePair> predicateIsCharge = new Predicate<TimePair>() {
            @Override
            public boolean test(TimePair timePair) {
                return timePair.getStayOverlapCount() > timePair.getAuthOverlapCout();
            }
        };

        private static final Predicate<TimePair> predicateNotInHoliday = new Predicate<TimePair>() {
            @Override
            public boolean test(TimePair timePair) {
                int authOverlapCout = timePair.getAuthOverlapCout();
                int stayOverlapCount = timePair.getStayOverlapCount();

                //在该时段有停留,但是该时段不在节假日内
                return stayOverlapCount > 0 && authOverlapCout == 0;
            }
        };

        public TimePair(Long startLong, Long endLong) {
            this(new Date(startLong), new Date(endLong));
        }

        public TimePair(Date startTime, Date endTime) {
            this.startTime = startTime;
            this.endTime = endTime;
            this.startLong = startTime.getTime();
            this.endLong = endTime.getTime();
            this.startString = dateToString(startTime, YYYY_MM_DD_HH_MM_SS);
            this.endString = dateToString(endTime, YYYY_MM_DD_HH_MM_SS);
        }

        public TimePair(String startString, String endString) {
            this.startString = startString;
            this.endString = endString;
            this.startTime = stringToDate(startString, YYYY_MM_DD_HH_MM_SS);
            this.endTime = stringToDate(endString, YYYY_MM_DD_HH_MM_SS);
            this.startLong = this.startTime.getTime();
            this.endLong = this.endTime.getTime();
        }


        public String getStartString() {
            return startString;
        }

        public void setStartString(String startString) {
            this.startString = startString;
        }

        public String getEndString() {
            return endString;
        }

        public void setEndString(String endString) {
            this.endString = endString;
        }

        public int getStayOverlapCount() {
            return stayOverlapCount;
        }

        public void setStayOverlapCount(int stayOverlapCount) {
            this.stayOverlapCount = stayOverlapCount;
        }

        public Date getStartTime() {
            return startTime;
        }

        public void setStartTime(Date startTime) {
            this.startTime = startTime;
        }

        public Date getEndTime() {
            return endTime;
        }

        public void setEndTime(Date endTime) {
            this.endTime = endTime;
        }

        public Long getStartLong() {
            return startLong;
        }

        public void setStartLong(Long startLong) {
            this.startLong = startLong;
        }

        public Long getEndLong() {
            return endLong;
        }

        public void setEndLong(Long endLong) {
            this.endLong = endLong;
        }

        public int getAuthOverlapCout() {
            return authOverlapCout;
        }

        public void setAuthOverlapCout(int authOverlapCout) {
            this.authOverlapCout = authOverlapCout;
        }


        public int caculateOverLapWith(Date startTime, Date endTime) {
            if (this.startLong == null) {
                this.startLong = this.startTime.getTime();
            }

            if (this.endLong == null) {
                this.endLong = this.endTime.getTime();
            }

            int incr = 0;
            if (this.startLong >= startTime.getTime() && this.endLong <= endTime.getTime()) {

                if (this.startLong != this.endLong) {


                    incr += 1;
                }
            }


            return incr;
        }

        public int caculateOverLapWithAuth(Date startTime, Date endTime) {
            int incr = caculateOverLapWith(startTime, endTime);
            if (incr > 0) {
                String startTimeStr = dateToString(startTime, YYYY_MM_DD_HH_MM_SS);
                String endTimeStr = dateToString(endTime, YYYY_MM_DD_HH_MM_SS);
                System.out.println(Parser.parse1("[包期时间]:    ({} ~ {})与时间段({} ~ {})有重叠", this.startString, this.endString, startTimeStr, endTimeStr));
            }
            this.authOverlapCout += incr;

            return this.authOverlapCout;
        }

        public int caculateOverLapWithStay(Date startTime, Date endTime) {
            int incr = caculateOverLapWith(startTime, endTime);
            if (incr > 0) {
                String startTimeStr = dateToString(startTime, YYYY_MM_DD_HH_MM_SS);
                String endTimeStr = dateToString(endTime, YYYY_MM_DD_HH_MM_SS);
                System.out.println(Parser.parse1("[停留时间]:    ({} ~ {})与时间段({} ~ {})有重叠", this.startString, this.endString, startTimeStr, endTimeStr));
            }
            this.stayOverlapCount += incr;
            return this.stayOverlapCount;
        }

        public boolean needCharge() {
            return predicateIsCharge.test(this);
//            return stayOverlapCount > authOverlapCout;
        }

        public boolean notInHoliday() {
            return predicateNotInHoliday.test(this);
        }


        public int caculateOverLapWithAuth(List<Date> dates) {
            int count = this.authOverlapCout;
            if (dates == null) {
                return count;
            }

            final int batch = 2;

            while (dates.size() >= batch) {
                List<Date> li = dates.subList(0, batch);
                count = caculateOverLapWithAuth(li.get(0), li.get(1));
                li.clear();
            }

            return count;
        }

        public int caculateOverLapWithStay(List<Date> dates) {
            int count = this.stayOverlapCount;
            if (dates == null) {
                return count;
            }

            final int batch = 2;

            while (dates.size() >= batch) {
                List<Date> li = dates.subList(0, batch);
                count = caculateOverLapWithStay(li.get(0), li.get(1));
                li.clear();
            }

            return count;
        }


        @Override
        public String toString() {
            if (startString == null) {
                startString = dateToString(startTime, YYYY_MM_DD_HH_MM_SS);
            }

            if (endString == null) {
                endString = dateToString(endTime, YYYY_MM_DD_HH_MM_SS);
            }

            return "(" + startString + " ~ " + endString + ") : auth:" + this.authOverlapCout + " stay:" + this.stayOverlapCount;
        }
    }


    private static class Pair<A, B> {
        public A first;
        public B second;

        public Pair(A first, B second) {
            this.first = first;
            this.second = second;
        }

        @Override
        public String toString() {
            return Parser.parse1("<{}, {}>\n\t",
                    first instanceof Date ? dateToString((Date) first, YYYY_MM_DD_HH_MM_SS) : first,
                    second instanceof Date ? dateToString((Date) second, YYYY_MM_DD_HH_MM_SS) : second);
        }
    }


    public interface Predicate<T> {
        public boolean test(T t);
    }






}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值