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