接到一个小需求,需要在指定时间段里每隔x分钟跑一段逻辑(如9:0:0-3:0:0 每隔90分钟执行一次)
原先打算用Quartz实现,翻阅了一下文档,似乎无法做到59分钟之外的增量。而且为了这么小一个需求硬塞一个库进去感觉有点不妥
折腾了一下午,在此把代码记录一下,有空加进自己的类库整理成工具类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
class TrSchedule{
//起始时间 24小时制
LocalDateTime startDate;
//结束时间
LocalDateTime endDate;

//间隔分钟
long delay;

public TrSchedule(String text){
String[] split = text.split(",");
String[] startDateSplit = split[0].split(":");
startDate = LocalDateTime.now();
startDate = startDate.withHour(Integer.valueOf(startDateSplit[0]))
.withMinute(Integer.valueOf(startDateSplit[1])).withSecond(Integer.valueOf(startDateSplit[2]));
String[] endDateSplit = split[1].split(":");
endDate = LocalDateTime.now();
endDate = endDate.withHour(Integer.valueOf(endDateSplit[0]))
.withMinute(Integer.valueOf(endDateSplit[1])).withSecond(Integer.valueOf(endDateSplit[2]));
delay = Long.parseLong(split[2]);
}

public LocalDateTime getStartDate() {
return startDate;
}

public LocalDateTime getEndDate() {
return endDate;
}

public long getDelay() {
return delay;
}
}

测试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
public class Main {

//测试用,存储时间
static LocalDateTime nextTime;

//存储执行时间
static long time;


public static void main(String[] args) {

DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

time = 0L;

//输出当前时间
nextTime = LocalDateTime.now();
System.out.println("当前时间:"+nextTime);

//表达式 (早上
String cron = "9:0:0,3:0:0,90";
TrSchedule trSchedule = new TrSchedule(cron);

for(int i=0;i<30;i++){

System.out.println("");
long m = getLastNextTimeM(nextTime,trSchedule);
time = (time==0L)?System.currentTimeMillis()+(m*60*1000):time+(m*60*1000);
System.out.println("开始第"+i+"周期任务还需"+m+"分钟(执行时间:"+dateFormat.format(new Date(time))+")");
System.out.println("");

}
}



public static long getLastNextTimeM(LocalDateTime currentDate,TrSchedule trSchedule){
LocalDateTime startDate = trSchedule.getStartDate().withDayOfMonth(currentDate.getDayOfMonth()).withDayOfYear(currentDate.getDayOfYear());
LocalDateTime endDate = trSchedule.getEndDate().withDayOfMonth(currentDate.getDayOfMonth()).withDayOfYear(currentDate.getDayOfYear());

//如果区间结束时间在开始时间之前(如8:00:0-3:0:0)
if(endDate.isBefore(startDate))
//将结束时间调整为下一天
endDate = endDate.plusDays(1);

//当前时间在区间结束时间之后时
if(currentDate.isAfter(endDate)){
nextTime = startDate.plusDays(1).plusMinutes(trSchedule.getDelay());
return getLast(currentDate,startDate.getHour(),startDate.getMinute(),startDate.getSecond())+trSchedule.getDelay();
}
//当前时间在开始时间之前
if(currentDate.isBefore(startDate)){
// 计算距离开始时间还有多久,再加上间隔时间返回
long rm = getLast(currentDate,startDate.getHour(),startDate.getMinute(),startDate.getSecond())+trSchedule.getDelay();
nextTime = currentDate.plusMinutes(rm);
return rm;
}else if(currentDate.isAfter(startDate)){
//返回的时间超出区间时
if(currentDate.plusMinutes(trSchedule.getDelay()).isAfter(endDate)){
long rm = getLast(currentDate,startDate.getHour(),startDate.getMinute(),startDate.getSecond())+trSchedule.getDelay();
nextTime = currentDate.plusMinutes(rm);
return rm;
}
//返回的时间未超出区间
nextTime = currentDate.plusMinutes(trSchedule.getDelay());
return trSchedule.getDelay();
}
return -1;
}

//计算 currentTime 与 传入 时分秒 还间隔多少分钟
public static long getLast(LocalDateTime currentTime,int hour, int minute,int s) {
LocalDateTime time = LocalDateTime.now();
time = time.withHour(hour);
time = time.withMinute(minute);
time = time.withSecond(0);
time = time.withDayOfMonth(currentTime.getDayOfMonth());
time = time.withDayOfYear(currentTime.getDayOfYear());
if (time.isBefore(currentTime))
time = time.plusDays(1L);
long re = time.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
return (re - currentTime.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli()) / 1000L/60L;
}
}

print测试一下吧

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
当前时间:2022-02-23T01:16:55.351
开始第0周期任务还需553分钟(执行时间:2022-02-23 10:29:55)
开始第1周期任务还需90分钟(执行时间:2022-02-23 11:59:55)
开始第2周期任务还需90分钟(执行时间:2022-02-23 13:29:55)
开始第3周期任务还需90分钟(执行时间:2022-02-23 14:59:55)
开始第4周期任务还需90分钟(执行时间:2022-02-23 16:29:55)
开始第5周期任务还需90分钟(执行时间:2022-02-23 17:59:55)
开始第6周期任务还需90分钟(执行时间:2022-02-23 19:29:55)
开始第7周期任务还需90分钟(执行时间:2022-02-23 20:59:55)
开始第8周期任务还需90分钟(执行时间:2022-02-23 22:29:55)
开始第9周期任务还需90分钟(执行时间:2022-02-23 23:59:55)
开始第10周期任务还需90分钟(执行时间:2022-02-24 01:29:55)
开始第11周期任务还需540分钟(执行时间:2022-02-24 10:29:55)
开始第12周期任务还需90分钟(执行时间:2022-02-24 11:59:55)
开始第13周期任务还需90分钟(执行时间:2022-02-24 13:29:55)
开始第14周期任务还需90分钟(执行时间:2022-02-24 14:59:55)
开始第15周期任务还需90分钟(执行时间:2022-02-24 16:29:55)
开始第16周期任务还需90分钟(执行时间:2022-02-24 17:59:55)
开始第17周期任务还需90分钟(执行时间:2022-02-24 19:29:55)
开始第18周期任务还需90分钟(执行时间:2022-02-24 20:59:55)
开始第19周期任务还需90分钟(执行时间:2022-02-24 22:29:55)
开始第20周期任务还需90分钟(执行时间:2022-02-24 23:59:55)
开始第21周期任务还需90分钟(执行时间:2022-02-25 01:29:55)
开始第22周期任务还需540分钟(执行时间:2022-02-25 10:29:55)
开始第23周期任务还需90分钟(执行时间:2022-02-25 11:59:55)
开始第24周期任务还需90分钟(执行时间:2022-02-25 13:29:55)
开始第25周期任务还需90分钟(执行时间:2022-02-25 14:59:55)
开始第26周期任务还需90分钟(执行时间:2022-02-25 16:29:55)
开始第27周期任务还需90分钟(执行时间:2022-02-25 17:59:55)
开始第28周期任务还需90分钟(执行时间:2022-02-25 19:29:55)
开始第29周期任务还需90分钟(执行时间:2022-02-25 20:59:55)

丢生产环境上跑,根据不同时间分配不同的表达式,算是完成了任务,有时间再想办法优化代码8
cron.png