5

彼ら、

ユーザーが毎月のジョブを(Quartzを使用して)スケジュールしています。ユーザーは、開始日fまたは実行する最初のジョブを提供します。これは、1〜31か月の任意の日である可能性があります。

私の質問は、すべての月に31、30、29日があるわけではないことを念頭に置いて、cronトリガーを使用してこれをスケジュールする方法です。このような場合、ジョブはその月の最も近い前日に実行する必要があります。つまり、4月は30日しかないので、ジョブは4月30日に実行する必要があります。

単一のcronトリガーを使用して実行できますか?それとも、トリガーの組み合わせである必要がありますか?私はCronExpressionを試して、そのようなケースをどのように処理するかを確認しました。

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

nextValidTimeは3月30日なので、cronは2月を「スキップ」しました。どんな助けでも大歓迎です。前もって感謝します。

4

4 に答える 4

6

「L」文字は、月日および曜日フィールドに使用できます。この文字 > は「最後」の省略形ですが、2 つのフィールドのそれぞれで異なる意味を持ちます。たとえば、日フィールドの値「L」は「月の最後の日」を意味します。1 月は 31 日、うるう年以外の 2 月は 28 日です。曜日フィールドで単独で使用する場合は、単に「7」または「SAT」を意味します。ただし、曜日フィールドで別の値の後に使用すると、「月の最後の xxx 日」を意味します。たとえば、「6L」は「月の最後の金曜日」を意味します。月の最終日からのオフセットを指定することもできます。たとえば、「L-3」は、暦月の最終日から 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 ? *");
}
于 2012-07-11T22:20:37.500 に答える
0

このスニペットを試してみてください。日によって 1 ~ 3 個のトリガー (1 年をカバー) が作成されます。

        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);
于 2013-12-04T13:59:50.977 に答える
0

前に述べたように、月の日数のケースごとに複数の 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, "?");
}

2 月の 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++;
        }
于 2014-10-12T12:04:44.230 に答える