使用Quartz每30天进行一次月度工作

ilu*_*ilu 4 java jobs triggers quartz-scheduler

伙计们,

我有用户安排的月度工作(使用Quartz).用户提供开始日期f或第一个要运行的作业,它可以是1-31个月的任何一天

我的问题是如何使用cron触发器安排此操作,记住并非所有月份都有31,30,29天.在这种情况下,作业应该在最接近的一个月中运行.所以,让我们说四月只有30天,所以工作必须在4月30日运行.

可以使用单个cron触发器完成吗?或者它应该是触发器的组合?我尝试使用CronExpression来查看它如何处理这种情况:

CronExpression ce = new CronExpression("0 0 0 30 JAN-DEC ? *");
Date nextValidTime = ce.getNextValidTimeAfter(//**27th of February**//);
Run Code Online (Sandbox Code Playgroud)

我的nextValidTime等于3月30日,所以cron只是"跳过"2月.任何帮助将受到高度赞赏.提前致谢.

Hit*_*eeb 6

"L"字符允许用于日期和星期几字段.这个字符>是"last"的简写,但它在两个字段的每一个中都有不同的含义.例如,日期字段中的值"L"表示"月份的最后一天" - 1月31日,非闰年2月28日.如果在星期几字段中单独使用,则仅表示"7"或"SAT".但是,如果在星期几字段中使用另一个值后,则表示"该月的最后一个xxx日" - 例如"6L"表示"该月的最后一个星期五".您还可以指定从该月的最后一天开始的偏移量,例如"L-3",这意味着该日历月的倒数第三天.使用"L"选项时,重要的是不要指定列表或值范围,因为您会收到令人困惑/意外的结果.

http://quartz-scheduler.org/api/2.0.0/org/quartz/CronExpression.html

new CronExpression("0 0 0 L JAN-DEC ? *");
Run Code Online (Sandbox Code Playgroud)

编辑:

我会做那样的事

Calendar tCalendar = Calendar.getInstance();
tCalendar.set(2009, Calendar.FEBRUARY/*int*/, 1); // for example Feb, 2009 -- day doesn't matter here
if(userSelectedDay > tCalendar.getActualMaximum(Calendar.DAY_OF_MONTH) ){
    //Fix user day
    //fixedDay = tCalendar.getActualMaximum(Calendar.DAY_OF_MONTH)

    // Or, for that month 
    //new CronExpression("0 0 0 L JAN-DEC ? *");
}
Run Code Online (Sandbox Code Playgroud)

  • 使用L(或任何变体Lx)对我的情况没有帮助.用户可以指定第一次运行作业的任何开始日期.从这个开始日期开始的日期必须用于每月运行工作.所以,它可能是1-31之间的任何东西.问题是29-31,因为并非所有月份都有.因此,如果用户选择了Janurary的30日,则工作必须在2月29日,3月30日,4月30日等运行.使用L-3将在2月25日(非闰年),3月28日发射 - 但这不是我需要的.作业必须在指定的日期或上一个最近的日期运行. (4认同)