5
votes

I'm trying to write a simple cron expression for quartz scheduler. I want the job to run every month on day 30 at 3am.

0 0 3 30 JAN-DEC ? *

I wonder what happens for the month of February? Will the job run or not run?

I'm not looking for a last day of month solution, I need the user to select the day of month when the job will run (ideally once for all months).

4

4 Answers

4
votes

L ("last") - has different meaning in each of the two fields in which it is allowed. For example, the value "L" in the day-of-month field means "the last day of the month" - day 31 for January, day 28 for February on non-leap years. If used in the day-of-week field by itself, it simply means "7" or "SAT". But if used in the day-of-week field after another value, it means "the last xxx day of the month" - for example "6L" means "the last friday of the month". When using the 'L' option, it is important not to specify lists, or ranges of values, as you'll get confusing results.

You can use this to specify instead of specifying 30 in your corn job directly.

http://www.quartz-scheduler.org/documentation/quartz-1.x/tutorials/crontrigger

Check for Special characters.

Thanks.

1
votes

It won't run. If you want it to run in the 28th in case of February, you have to create multiple CronExpressions for each case of days in month, and a trigger for each one, and then add all the triggers to your required Job.

This is what I have done:

CronExpressions creation:

public static List<CronExpression> getCronExpressionList(int seconds, int minutes,
            int hours, int dayInMonth, Month month,
            DayOfWeek dayOfWeek) {
    final String monthsWith30Days = Month.APR + "," + Month.JUN + ","
                    + Month.SEP + "," + Month.NOV;
    List<CronExpression> crons = new LinkedList<CronExpression>();

    String timeString = String.format(("%s %s %s "), seconds, minutes,
                    hours, 0, 0, 0);
    String dateString = "%s %s %s";
    String cron = null;

    cron = timeString + String.format(dateString, dayInMonth, "*", "?");
    crons.add(new CronExpression(cron));
    if (dayInMonth > 28) {
        String febCron = timeString + getFebruarLastDayDateString(dateString);
        crons.add(new CronExpression(febCron));
        if (dayInMonth == 31) {
            String monthsWithThirtyDaysCron = timeString + String.format(dateString,
                    "L", monthsWith30Days, "?");
            crons.add(new CronExpression(monthsWithThirtyDaysCron));
        }
    }
    return crons;
}

private static String getFebruarLastDayDateString(String initialCron) 
               throws ParseException {
    return String.format(initialCron, "L", Month.FEB, "?");
}

Trigger creation:

        Set<CronTrigger> triggers = new HashSet<>();

        int i = 1;
        for (CronExpression cronEx : cronsList) {
            CronTrigger trigger = newTrigger()
                    .withIdentity("trigger" + i, groupName)
                    .withSchedule(cronSchedule(cronEx))
                    .build();
                triggers.add(trigger);
                i++;
        }
0
votes

check simple code

public class TestCronTrigger {

    private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd");

    public static void main(String[] args) throws Exception {

        String dateStr = "2015-02-10";
        String cron = "0 0 0 31 * ?";
        Date nextFireTime = getNextFireTimeFromDateForCron(DATE_FORMAT.parse(dateStr), cron);
        System.out.println(String.format("For cron '%s' next fire time after '%s' will be '%s'", cron, dateStr, DATE_FORMAT.format(nextFireTime)));

        dateStr = "2015-02-10";
        cron = "0 0 0 30 * ?";
        nextFireTime = getNextFireTimeFromDateForCron(DATE_FORMAT.parse(dateStr), cron);
        System.out.println(String.format("For cron '%s' next fire time after '%s' will be '%s'", cron, dateStr, DATE_FORMAT.format(nextFireTime)));

        dateStr = "2015-02-10";
        cron = "0 0 0 28 * ?";
        nextFireTime = getNextFireTimeFromDateForCron(DATE_FORMAT.parse(dateStr), cron);
        System.out.println(String.format("For cron '%s' next fire time after '%s' will be '%s'", cron, dateStr, DATE_FORMAT.format(nextFireTime)));

        dateStr = "2015-03-10";
        cron = "0 0 0 31 * ?";
        nextFireTime = getNextFireTimeFromDateForCron(DATE_FORMAT.parse(dateStr), cron);
        System.out.println(String.format("For cron '%s' next fire time after '%s' will be '%s'", cron, dateStr, DATE_FORMAT.format(nextFireTime)));

    }

    static Date getNextFireTimeFromDateForCron(Date from, String cron) throws ParseException {
        CronTriggerImpl cronTrigger = new CronTriggerImpl();
        cronTrigger.setCronExpression(cron);
        cronTrigger.setStartTime(from);
        return cronTrigger.computeFirstFireTime(null);
    }
}

For this code the output will be:

For cron '0 0 0 31 * ?' next fire time after '2015-02-10' will be '2015-03-31'
For cron '0 0 0 30 * ?' next fire time after '2015-02-10' will be '2015-03-30'
For cron '0 0 0 28 * ?' next fire time after '2015-02-10' will be '2015-02-28'
For cron '0 0 0 31 * ?' next fire time after '2015-03-10' will be '2015-03-31'

playing with arguments you can find answers

0
votes

The below code calculates the next fire date for the last day of every month

static Date getNextFireTimeFromDateForCron() throws ParseException {
    CronTriggerImpl cronTrigger = new CronTriggerImpl();
    cronTrigger.setCronExpression("0 15 15 L * ?");
    cronTrigger.setStartTime(new Date());
    return cronTrigger.computeFirstFireTime(null);
}