在使用Quartz每30天月度就业(Monthly jobs on every 30th day u

2019-09-19 08:51发布

伙计们,

我有月度就业由用户计划(使用Quartz)。 用户提供的开始日期F或第一份工作运行,也可能是1-31个月的任何一天

My question is how to schedule this using cron trigger, having in mind that not all month have 31,30,29th days. In such case job should run closest previous day of the month. So, lets say April has only 30 days, so job has to run on 30th of April.

它可以使用单触发的cron来完成? 还是应触发的组合? 我试着用CronExpression玩,看看它是如何处理这样的情况:

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

我有nextValidTime等于月30日 ,这样的cron只是“略过”二月。 任何帮助将高度赞赏。 提前致谢。

Answer 1:

该“L”字符是允许的和日常的周田天个月,。 这个字符>是短手“最后”,但它在每两个领域的不同的含义。 例如,在某一天的月字段中的值“L”的意思是“这个月的最后一天” - 49日在非闰年的月份,有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 ? *");

编辑:

我只想做这样的事情再

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 ? *");
}


Answer 2:

这里是我的解决方案。 这个想法是试图建立一组将被传递到一个触发生成器的cron表达式。

  • 如果输入天<28使用一个单一的表达:
  • 如果输入天= 29或= 30. 2个表达式:二月的最后一天,而其他月份的某一天。
  • 如果输入天= 31使用月份的最后一天。

     public static Set<String> byDay(int day) { if (day < 1 || day > 31) { throw new IllegalArgumentException("The input day must be in range: 1 <= day <= 31"); } if (day <= 28) { return Collections.singleton(String.format("0 0 0 %d JAN-DEC ? *", day)); } if (day == 29 || day == 30) { Set<String> expressions = new HashSet<String>(); expressions.add("0 0 0 L FEB ? *"); expressions.add(String.format("0 0 0 %d JAN,MAR,APR,MAY,JUN,JUL,AUG,SEP,OCT,NOV,DEC ? *", day)); return Collections.unmodifiableSet(expressions); } // day == 31 return Collections.singleton("0 0 0 L * ? *"); } 


Answer 3:

试试这个片段中,从1到3触发器根据一天(涵盖了全年)创建:

        Set<Trigger> triggers = new HashSet<>(3);

        CronScheduleBuilder interval = CronScheduleBuilder.monthlyOnDayAndHourAndMinute(dayNumber, 0, 0);

        if (dayNumber > 28) {
            CronTrigger trigger28 = TriggerBuilder.newTrigger()
                    .withIdentity("payment_trigger28_" + merchantServiceTemplate.getId(), "payment_triggers")
                    .withSchedule(CronScheduleBuilder.cronSchedule("0 0 0 28 2 ? *"))
                    .endAt(merchantServiceTemplate.getEndScheduleDate())
                    .build();
            triggers.add(trigger28);

            if (dayNumber == 31) {
                CronTrigger trigger30 = TriggerBuilder.newTrigger()
                        .withIdentity("payment_trigger30_" + merchantServiceTemplate.getId(), "payment_triggers")
                        .withSchedule(CronScheduleBuilder.cronSchedule("0 0 0 30 4,6,9,11 ? *"))
                        .endAt(merchantServiceTemplate.getEndScheduleDate())
                        .build();
                triggers.add(trigger30);
            }
        }

        Trigger trigger = TriggerBuilder.newTrigger()
                .withIdentity("payment_triggerAll_" + merchantServiceTemplate.getId(), "payment_triggers")
                .withSchedule(interval)
                .endAt(merchantServiceTemplate.getEndScheduleDate())
                .build();
        triggers.add(trigger);


        scheduler.scheduleJob(job, triggers, false);


Answer 4:

正如前面所说的,你要在一个月的天每种情况下,并为每一个触发创建多个CronExpressions,然后所有触发器添加到您需要的工作。

这是我的版本:

CronExpressions创作:

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, "?");
}

注意,我在二月的cron使用“L”,否则你将不得不在闰年的错误。

创建触发器:

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


文章来源: Monthly jobs on every 30th day using Quartz