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); } }