java-计算发送时间

package cn.com.fl.service.utils;


import cn.com.doone.tocloud.tools.MyLogUtil;
import cn.com.doone.tocloud.tools.MyLogger;

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


public class ComputeSendTimeUtil {

    static MyLogger logger = MyLogUtil.getLogger(ComputeSendTimeUtil.class);

    /**
     * 计算发送时间
     * @param lastSendTime   yyyy-MM-dd HH:mm:ss
     * @return
     */
    public static String computeSendTime(String lastSendTime,String rules,List<String> timeNodeList,int rowNum){
        logger.log(MyLogUtil.LOG_INFO,"进入计算发送时间");
        String sendTime = "";
        Date now = new Date();
        // 根据配置获取时间范围 时:分 格式例如(08:00  12:00  14:00  20:00)
        List<String> timeList = new ArrayList<>(Arrays.asList(rules.split("-")));
        String strStartTime1 = timeList.get(0).substring(0,timeList.get(0).lastIndexOf(":"));
        String strEndTime1 = timeList.get(1).substring(0,timeList.get(1).lastIndexOf(":"));
        String strStartTime2 = timeList.get(2).substring(0,timeList.get(2).lastIndexOf(":"));
        String strEndTime2 = timeList.get(3).substring(0,timeList.get(3).lastIndexOf(":"));

        SimpleDateFormat sdfHM = new SimpleDateFormat("HH:mm");
        String nowStr = sdfHM.format(now);

        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        SimpleDateFormat sdfYMD = new SimpleDateFormat("yyyy-MM-dd");
        try {
            Date date = sdf.parse(lastSendTime);
            String zeroTimeHMStr = "00:00";
            Date zeroTime = sdfHM.parse(zeroTimeHMStr);
            String nowStrYMD = sdfYMD.format(now);

            //HH:mm格式的当前时间
            Date nowTime  = sdfHM.parse(nowStr);
            //上午时间区间String转Date
            Date startTime1 = sdfHM.parse(strStartTime1);
            Date endTime1  = sdfHM.parse(strEndTime1);
            //下午时间区间String转Date
            Date startTime2 = sdfHM.parse(strStartTime2);
            Date endTime2  = sdfHM.parse(strEndTime2);
            // 最后一条发送时间是否超过当前时间
            if(date.compareTo(now) <= 0){ // 不超过
                logger.log(MyLogUtil.LOG_INFO,"最后一条发送时间("+lastSendTime+")不超过当前时间:");
                // 当前时间是否在规则时间范围内
                if (isEffectiveDate(nowTime, startTime1, endTime1) || isEffectiveDate(nowTime, startTime2, endTime2)) {
                    System.out.println("当前时间在时间段内["+strStartTime1+","+strEndTime1+"]或["+strStartTime2+","+strEndTime2+"]");
                    Date newTime = now;
                    while (true){
                        if(timeNodeList.contains(nowStr)){ // 如果正好在时间节点上
                            // 生成发送时间
                            sendTime = setTime(nowStrYMD,nowStr,rowNum);
                            break;
                        }else{ // 如果不在时间节点上 就加1分钟,再进循环去判断,直到匹配到后跳出循环返回数据
                            newTime = new Date(newTime.getTime() + 60000);
                            Date newTimeHM = sdfHM.parse(sdfHM.format(newTime));
                            if (isEffectiveDate(newTimeHM, startTime1, endTime1) || isEffectiveDate(newTimeHM, startTime2, endTime2)) {
                                nowStr = sdfHM.format(newTime);
                            }else{
                                // 直接生成发送时间(虽然超出了范围一点)
                                nowStr = sdfHM.format(newTime);
                                sendTime = setTime(nowStrYMD,nowStr,rowNum);
                                break;
                            }
                        }
                    }
                } else {
                    System.out.println("当前时间不在时间段内["+strStartTime1+","+strEndTime1+"]或["+strStartTime2+","+strEndTime2+"]");
                    // 判断是否在 zeroTime -  startTime1 (0:00 -  08:00) 区间
                    if(isEffectiveDate(nowTime, zeroTime, startTime1)){
                        // 生成发送时间
                        sendTime = setTime(nowStrYMD,strStartTime1,rowNum);
                    } // 判断是否在 endTime1 -  startTime2 (12:00 -  14:00) 区间
                    else if(isEffectiveDate(nowTime, endTime1, startTime2)){
                        // 生成发送时间
                        sendTime = setTime(nowStrYMD,strStartTime2,rowNum);
                    }else { // 说明时间超过了 endTime2 20:00
                        // 日期加 1 天
                        Date secondDate = dateAddOne(now);
                        String secondDateStr = sdfYMD.format(secondDate);
                        // 生成发送时间
                        sendTime = setTime(secondDateStr,strStartTime1,rowNum);
                    }
                }
            }else{  // 超过
                logger.log(MyLogUtil.LOG_INFO,"最后一条发送时间("+lastSendTime+")超过当前时间:");
                // 获取发送时间分钟数匹配下一个时间节点加上随机数
                Date lastSendTimeDate = sdf.parse(lastSendTime);
                // 先随机加分钟数
                Date afterLastSendTimeDate = new Date(lastSendTimeDate.getTime() + rowNum * 60000);

                String lastSendTimeYMD = sdfYMD.format(lastSendTimeDate);  // 获取日期字符串 yyyy-MM-dd
                String lastSenfTimeHM = sdfHM.format(afterLastSendTimeDate);  // 获取时分字符串 HH:mm
                Date lastSendTimeDateHM = sdfHM.parse(sdfHM.format(sdf.parse(lastSendTime))); // 获取时分 HH:mm
                // 获取的最后时间是否在规则时间范围内
                if (isEffectiveDate(lastSendTimeDateHM, startTime1, endTime1) || isEffectiveDate(lastSendTimeDateHM, startTime2, endTime2)) {
                    System.out.println("最后发送时间在时间段内["+strStartTime1+","+strEndTime1+"]或["+strStartTime2+","+strEndTime2+"]");
                    Date newTime = afterLastSendTimeDate;
                    while (true){
                        if(timeNodeList.contains(lastSenfTimeHM)){ // 如果正好在时间节点上
                            // 生成发送时间
                            sendTime = setTime(lastSendTimeYMD,lastSenfTimeHM,rowNum);
                            break;
                        }else{ // 如果不在时间节点上 就加1分钟,再进循环去判断,直到匹配到后跳出循环返回数据
                            newTime = new Date(newTime.getTime() + 60000);
                            Date newTimeHM = sdfHM.parse(sdfHM.format(newTime));
                            if (isEffectiveDate(newTimeHM, startTime1, endTime1) || isEffectiveDate(newTimeHM, startTime2, endTime2)) {
                                lastSenfTimeHM = sdfHM.format(newTime);
                            }else{
                                // 直接生成发送时间(虽然超出了范围一点)
                                lastSenfTimeHM = sdfHM.format(newTime);
                                sendTime = setTime(lastSendTimeYMD,lastSenfTimeHM,rowNum);
                                break;
                            }
                        }
                    }
                }else{
                    System.out.println("最后发送时间不在时间段内["+strStartTime1+","+strEndTime1+"]或["+strStartTime2+","+strEndTime2+"]");
                    // 判断是否在 zeroTime -  startTime1 (0:00 -  08:00) 区间
                    if(isEffectiveDate(lastSendTimeDateHM, zeroTime, startTime1)){
                        // 生成发送时间
                        sendTime = setTime(lastSendTimeYMD,strStartTime1,rowNum);
                    } // 判断是否在 endTime1 -  startTime2 (12:00 -  14:00) 区间
                    else if(isEffectiveDate(lastSendTimeDateHM, endTime1, startTime2)){
                        // 生成发送时间
                        sendTime = setTime(lastSendTimeYMD,strStartTime2,rowNum);
                    }else { // 说明时间超过了 endTime2 20:00
                        // lastSendTimeYMD 日期加 1 天
                        Date secondDate = dateAddOne(lastSendTimeDate);
                        String secondDateStr = sdfYMD.format(secondDate);
                        // 生成发送时间
                        sendTime = setTime(secondDateStr,strStartTime1,rowNum);
                    }
                }

            }
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return sendTime;
    }

    /**
     * 生成发送时间
     * @param rq  2022-04-14
     * @param sj  14:00
     * @param rowNum 5
     * @return
     */
    public static String setTime(String rq,String sj,int rowNum){
        logger.log(MyLogUtil.LOG_INFO,"进入生成发送时间:[日期:" + rq + ",时分:" + sj + ",随机数:" +rowNum);
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String sendTime = "";
        String timeStr = rq + " " + sj + ":00";  // 拼接格式 yyyy-MM-dd HH:mm:ss
        Date timeDate = null;
        try {
            timeDate = sdf.parse(timeStr);
            // 分钟数据加上随机分钟数
            Date afterDate = new Date(timeDate.getTime() + rowNum * 60000);
            sendTime = sdf.format(afterDate);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return sendTime;
    }

    /**
     * 判断当前时间是否在[startTime, endTime]区间,注意三个参数的时间格式要一致
     * @param nowTime  同格式 (14:34)
     * @param startTime  14:00
     * @param endTime  20:00
     * @return 在时间段内返回true,不在返回false
     */
    public static boolean isEffectiveDate(Date nowTime, Date startTime, Date endTime) {
        if (nowTime.getTime() == startTime.getTime()
                || nowTime.getTime() == endTime.getTime()) {
            return true;
        }

        Calendar date = Calendar.getInstance();
        date.setTime(nowTime);

        Calendar begin = Calendar.getInstance();
        begin.setTime(startTime);

        Calendar end = Calendar.getInstance();
        end.setTime(endTime);

        return date.after(begin) && date.before(end);
    }

    /**
     * 日期加+1天
     * @param date
     * @return
     */
    public static Date dateAddOne(Date date) {
        Calendar calendar = new GregorianCalendar();
        calendar.setTime(date);
        calendar.add(calendar.DATE, 1); //把日期往后增加一天,整数  往后推,负数往前移动
        date = calendar.getTime(); //这个时间就是日期往后推一天的结果
        return date;
    }

    /**
     * 时间段相差分钟数
     * @param startTime 开始时间 14:00
     * @param endTime   结束时间 20:00
     * @return
     */
    public static long differMin(String startTime,String endTime){
        long minute = -1;
        SimpleDateFormat sdfHM = new SimpleDateFormat("HH:mm");
        try {
            Date startTimeDate = sdfHM.parse(startTime);
            Date endTimeDate = sdfHM.parse(endTime);
            minute = (endTimeDate.getTime() - startTimeDate.getTime())/1000/60;
            System.out.println(minute);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return minute;
    }

    /**
     * 根据两个时间范围计算每一个发送的时间节点和间隔时间差
     * @param startTimeStr1  早上开始时间 08:00
     * @param endTimeStr1    早上结束时间 12:00
     * @param startTimeStr2  下午开始时间 14:00
     * @param endTimeStr2    下午结束时间 20:00
     * @param count          每天每个员工最多添加个数
     * @return
     */
    public static Map<String,Object>  timeNode (String startTimeStr1, String endTimeStr1, String startTimeStr2, String endTimeStr2, long count){
        logger.log(MyLogUtil.LOG_INFO,"进入计算时间节点");
        Map<String,Object> resultMap = new HashMap<>();
        List<String> timeNodeList = new ArrayList<>();
        long num = 1;
        try {
            SimpleDateFormat sdfHM = new SimpleDateFormat("HH:mm");
            Date startTimeDate1 = sdfHM.parse(startTimeStr1);
            Date endTimeDate1 = sdfHM.parse(endTimeStr1);
            Date startTimeDate2 = sdfHM.parse(startTimeStr2);
            Date endTimeDate2 = sdfHM.parse(endTimeStr2);

            // 计算总分钟数(用时间段相差分钟数)
            long a = differMin(startTimeStr1,endTimeStr1);
            long b = differMin(startTimeStr2,endTimeStr2);
            long min = a + b;
            // 计算时间节点相差分钟数
            num = min/count;
            // 算出第2个时间范围的所有时间节点
            Date nextTimeNodeDate1 = startTimeDate1;
            while (true){
                if(isEffectiveDate(nextTimeNodeDate1,startTimeDate1,endTimeDate1)){
                    String nextTimeNodeStr = sdfHM.format(nextTimeNodeDate1);
                    timeNodeList.add(nextTimeNodeStr);
                    nextTimeNodeDate1 = new Date(nextTimeNodeDate1.getTime() + num * 60000);
                }else{
                    // 如果数组包含最后一个节点就删除掉
                    if(timeNodeList.contains(endTimeStr1)){
                        // 删除最后一个元素 12:00 剩下以下的节点
                        // [08:00, 08:12, 08:24, 08:36, 08:48, 09:00, 09:12, 09:24, 09:36, 09:48, 10:00, 10:12, 10:24, 10:36, 10:48, 11:00, 11:12, 11:24, 11:36, 11:48]
                        timeNodeList.remove(timeNodeList.size()-1);
                    }
                    break;
                }
            }
            // 算出第2个时间范围的所有时间节点
            Date nextTimeNodeDate2 = startTimeDate2;
            while (true){
                if(isEffectiveDate(nextTimeNodeDate2,startTimeDate2,endTimeDate2)){
                    String nextTimeNodeStr = sdfHM.format(nextTimeNodeDate2);
                    timeNodeList.add(nextTimeNodeStr);
                    nextTimeNodeDate2 = new Date(nextTimeNodeDate2.getTime() + num * 60000);
                }else{
                    // 如果数组包含最后一个节点就删除掉
                    if(timeNodeList.contains(endTimeStr2)){
                        // 删除最后一个元素 20:00 剩下以下的节点
                        timeNodeList.remove(timeNodeList.size()-1);
                    }
                    break;
                }
            }
            System.out.println("时间节点:" + timeNodeList);

        } catch (ParseException e) {
            e.printStackTrace();
        }
        resultMap.put("timeNodeList",timeNodeList);
        resultMap.put("num",num);
        return resultMap;
    }



    public static void main(String[] args) {

        String rules = "08:00:00-12:00:00-14:00:00-20:00:00"; // // 做成配置传进来后续
        List<String> timeNodeList = new ArrayList<>(); // 时间节点后续根据以上配置算好传进来
        timeNodeList.add("08:00");timeNodeList.add("08:12");timeNodeList.add("08:24");timeNodeList.add("08:36");timeNodeList.add("08:48");
        timeNodeList.add("09:00");timeNodeList.add("09:12");timeNodeList.add("09:24");timeNodeList.add("09:36");timeNodeList.add("09:48");
        timeNodeList.add("10:00");timeNodeList.add("10:12");timeNodeList.add("10:24");timeNodeList.add("10:36");timeNodeList.add("10:48");
        timeNodeList.add("11:00");timeNodeList.add("11:12");timeNodeList.add("11:24");timeNodeList.add("11:36");timeNodeList.add("11:48");

        timeNodeList.add("14:00");timeNodeList.add("14:12");timeNodeList.add("14:24");timeNodeList.add("14:36");timeNodeList.add("14:48");
        timeNodeList.add("15:00");timeNodeList.add("15:12");timeNodeList.add("15:24");timeNodeList.add("15:36");timeNodeList.add("15:48");
        timeNodeList.add("16:00");timeNodeList.add("16:12");timeNodeList.add("16:24");timeNodeList.add("16:36");timeNodeList.add("16:48");
        timeNodeList.add("17:00");timeNodeList.add("17:12");timeNodeList.add("17:24");timeNodeList.add("17:36");timeNodeList.add("17:48");
        timeNodeList.add("18:00");timeNodeList.add("18:12");timeNodeList.add("18:24");timeNodeList.add("18:36");timeNodeList.add("18:48");
        timeNodeList.add("19:00");timeNodeList.add("19:12");timeNodeList.add("19:24");timeNodeList.add("19:36");timeNodeList.add("19:48");

        int rowNum = 5; // 后续外面根据随机数生成规则传进来
//        String sendTime = computeSendTime("2010-01-01 10:00:00",rules,timeNodeList,7);
//        String sendTime = computeSendTime("2022-04-16 19:59:00",rules,timeNodeList,-4);
//        String sendTime = computeSendTime("2022-04-18 20:15:00",rules,timeNodeList,rowNum);
//        System.out.println(sendTime);

    }
}

 

posted @ 2023-04-26 09:41  梦幻&浮云%  阅读(32)  评论(0编辑  收藏  举报