【问题标题】:Quartz cron - what if the day of month does not exist?Quartz cron - 如果月份中的某天不存在怎么办?
【发布时间】:2012-01-23 13:08:05
【问题描述】:

我正在尝试为石英调度程序编写一个简单的 cron 表达式。我希望该作业在每个月的第 30 天凌晨 3 点运行。

0 0 3 30 JAN-DEC ? *

我想知道二月份会发生什么?作业会运行还是不运行?

我不是在寻找每月最后一天的解决方案,我需要用户选择作业将在每月的哪一天运行(最好是所有月份一次)。

【问题讨论】:

    标签: java cron quartz-scheduler


    【解决方案1】:

    L(“最后一个”) - 在允许使用的两个字段中的每个字段中都有不同的含义。例如,day-of-month 字段中的值“L”表示“月的最后一天”——非闰年 1 月的第 31 天,2 月的第 28 天。如果单独在星期几字段中使用,它仅表示“7”或“SAT”。但是如果在星期几字段中使用另一个值,则表示“本月的最后 xxx 天”——例如“6L”表示“本月的最后一个星期五”。使用“L”选项时,重要的是不要指定列表或值范围,因为您会得到令人困惑的结果。

    您可以使用它来指定而不是直接在您的玉米作业中指定 30。

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

    检查特殊字符。

    谢谢。

    【讨论】:

    • 好吧,我不感兴趣在本月的最后一天或倒数第二天运行该作业。我只需要它在 30 岁(如果那一天存在的话)。
    【解决方案2】:

    它不会运行。如果您希望它在 2 月的情况下在 28 日运行,则必须为每个月的天数创建多个 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, "?");
    }
    

    触发器创建:

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

    【讨论】:

      【解决方案3】:

      检查简单代码

      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 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'
      

      玩弄你能找到答案的论据

      【讨论】:

      • 这只是一个间接的答案。如果您可以为 OP 给出的值添加您获得的输出,我会很棒。这将使您的答案更加完整。
      【解决方案4】:

      下面的代码计算每个月最后一天的下一个触发日期

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

      【讨论】:

        猜你喜欢
        • 2011-06-22
        • 2010-10-06
        • 2019-01-22
        • 1970-01-01
        • 2015-05-14
        • 1970-01-01
        • 2022-06-13
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多