Кварц CronTrigger - Начало следующего огня - PullRequest
19 голосов
/ 11 августа 2011

Я использую Quartz CronTrigger для анализа строк формата расписания cron, чтобы определить, когда должно выполняться конкретное задание. На самом деле я не использую Quartz для планирования работы.

В CronTrigger есть метод getFireTimeAfter (Date), который дает следующий раз, когда задание будет запущено после указанной даты. Это хорошо работает, когда указана дата сейчас или в будущем. Но, похоже, это не сработает, если дата в прошлом.

Date currTime = new Date();
CronTrigger tr = new CronTrigger();
tr.setCronExpression("0 0 23 3,18 * ? *");
Date nextFireAt = tr.getFireTimeAfter(currTime);
System.out.println("Reference time: " + currTime);
System.out.println("Next fire after reference time: " + nextFireAt);

График работы cron для стрельбы в 23:00 3 и 18 числа каждого месяца. Так, например, если я сделал это сегодня (11 августа), я вижу:

Reference time: Thu Aug 11 10:04:25 MDT 2011
Next fire after reference time: Thu Aug 18 23:00:00 MDT 2011

Но если я установлю контрольную дату в прошлое, это даст мне то же самое время следующего огня

Reference time: Wed Dec 31 17:00:00 MST 1969
Next fire after reference time: Thu Aug 18 23:00:00 MDT 2011

Я ожидал, что результат будет:

Reference time: Wed Dec 31 17:00:00 MST 1969
Next fire after reference time: Wed Aug 3 23:00:00 MDT 2011

Метод просто не предназначен для такой работы или я что-то не так делаю?

Спасибо!

Ответы [ 5 ]

33 голосов
/ 11 августа 2011

То, что вы действительно хотите использовать объект CronExpression напрямую, а не CronTrigger.Как вы обнаружили, он не будет вычислять время следующего запуска в прошлом ... но CronExpression будет!

CronExpression имеет метод: getNextValidTimeAfter.Это то, что вы хотите.

4 голосов
/ 03 декабря 2015

В Spring вы можете следовать тому же подходу, который они используют в своих интеграционных тестах. CronTriggerTests

CronTrigger trigger = new CronTrigger();
trigger.setCronExpression("0 0 23 3,18 * ? *");
SimpleTriggerContext triggerContext = new SimpleTriggerContext();
triggerContext.update(null, null, new Date());
Date nextFireAt = trigger.nextExecutionTime(triggerContext);
1 голос
/ 30 января 2012

Метод CronTrigger.getFireTimeAfter() имеет защитный механизм для предотвращения того, что указанное позднее время будет в прошлом.

Этого можно обойти, позвонив setStartTime Ферт с указанным вами временем в прошлом. Тогда вызов getFireTimeAfter должен вернуться с верным результатом.

0 голосов
/ 05 мая 2014

Это немного странно, но механизм защиты существует. Понятия не имею, почему у Кварц Команды такая проверка Тест ниже, только если я добавлю час к nxtDay (nxtDay = nxtTrigger.Value.DateTime.AddHours(1);)

var timeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById("GMT Standard Time");

//FREQUENCY OF SECONDS 
var reccurrence = new Reccurrence
{
    StartTime = new TimeSpan(9, 0, 0),
    StopTime = new TimeSpan(11, 0, 0),
    WeekDay = "MON-SUN",
    TimeZoneInfo = timeZoneInfo,
    Frequency = 15,
    FrequencyUnit = FrequencyUnit.Seconds
};

var autoPublishDetail = new AutoPublishJobDetail("TestReccurence_Seconds", _log, null, reccurrence);
var trigger = autoPublishDetail.GetDailyTrigger();
var nxt = trigger.GetNextFireTimeUtc();

var jobSeconds = JobBuilder.Create().WithIdentity(new JobKey("TestReccurence_Seconds")).OfType(typeof(AutoPublishJob)).Build();

_scheduler.ScheduleJob(jobSeconds, trigger);

//This job sud run 4 times in a 60 secs and from 9 am to 11 am (Span of 3 hrs including 11 onwards to 11:59:59)
//Total runs = 4 x 60 x 3 = 720
var today = DateTime.Now;
var tomorrow = today.AddDays(1);
DateTime? nxtDay = new DateTime(tomorrow.Year, tomorrow.Month, tomorrow.Day);

int jobCnt = 0;
do
{
    var nxtTrigger = trigger.GetFireTimeAfter(nxtDay.Value);

    if (nxtTrigger.Value.Year.Equals(today.AddDays(2).Year) && nxtTrigger.Value.Month.Equals(today.AddDays(2).Month) && nxtTrigger.Value.Day.Equals(today.AddDays(2).Day))
        break;

    jobCnt++;
    nxtDay = nxtTrigger.Value.DateTime.AddHours(1);

} while (true);

Assert.AreEqual(720, jobCnt);
0 голосов
/ 11 августа 2011

В соответствии с Кварцевым документом :

Возвращает в следующий раз, когда CronTrigger выстрелит, после заданного времени

"Воляогонь "подразумевает" в будущем ".То есть в следующий раз, когда CronTrigger выстрелит, не в прошлом, а даты в прошлом не возвращаются.

Я не знаю точно, что вы пытаетесь достичь, но вы ночьюбыть заинтересованным в этих методах:

  • getPreviousFireTime (): возвращает время последнего срабатывания триггера
  • getTimeBefore (): возвращает время срабатывания триггера до заданной даты (работает вПрошлое) - Примечание: на данный момент это кажется нереализованным
...