TL;DR
在Quartz 1中,你可以使用这个cron: 59 59 23 31 12 ? 2099
(最后一个有效日期)。
在Quartz 2中,你可以使用这个cron: 0 0 0 1 1 ? 2200
使用远期表达式
使用org.quartz.CronExpression
进行了一些快速测试。
String exp = "0 0 0 1 1 ? 3000";
boolean valid = CronExpression.isValidExpression(exp);
System.out.println(valid);
if (valid) {
CronExpression cronExpression = new CronExpression(exp);
System.out.println(cronExpression.getNextValidTimeAfter(new Date()));
}
当我执行
String exp = "# 0 0 0 1 1 ?";
时,
isValid
测试返回
false
。
尽管使用了上面给出的示例,输出如下:
true
null
含义:
- 该表达式是有效的;
- 没有即将到来的日期与此表达式匹配。
然而,为了使调度程序接受cron触发器,后者必须匹配未来的某个日期。
我尝试了几年,并发现一旦年份超过2300年,Quartz似乎就不再关心了(尽管我没有在Quartz 2的文档中找到年份的最大值的提及)。可能有更简洁的方法来解决这个问题,但现在这样做已经满足了我的需求。
因此,最终我建议使用的cron表达式是0 0 0 1 1 ? 2200
。
Quartz 1 变体
请注意,在Quartz 1中,
2099是最后一个有效的年份。因此,您可以根据
Maciej Matys的建议调整cron表达式:
59 59 23 31 12?2099
备选方案:使用过去的日期
Arnaud Denoyelle提出了一种更优雅的解决方案,我的测试证实这是一个正确的表达式:不要选择一个遥远的未来日期,而是选择一个遥远的过去日期:
0 0 0 1 1?1970
(根据Quartz文档,这是第一个有效的表达式)。
但是,这个解决方案并不起作用。
hippofluff指出,Quartz会检测到过去的表达式永远不会再次执行,因此会抛出异常。
org.quartz.SchedulerException: Based on configured schedule, the given trigger will never fire.
这似乎已经在Quartz中很长时间了。
教训:测试并不是绝对可靠的
这凸显了我的测试的一个弱点:如果您想测试一个CronExpression
,请记住它必须有一个nextValidTime
1。否则,您将传递给它的调度程序将仅使用上述异常拒绝它。
我建议按以下方式调整测试代码:
String exp = "0 0 0 1 1 ? 3000";
boolean valid = CronExpression.isValidExpression(exp);
if (valid) {
CronExpression cronExpression = new CronExpression(exp);
valid = cronExpression.getNextValidTimeAfter(new Date()) != null;
}
System.out.println("Can I use <" + exp + ">? " + (valid ? "Go ahead!" : "This shall fail."));
这里有:无需思考,只需阅读输出。
1. 这是我在测试Arnaud的解决方案时忘记的部分,让我变成了傻瓜并证明我的测试不是无法出错的。
#
注释字符开头的命令。 - Barmar