Quartz CronTrigger - 获得下一个火力时间

时间:2011-08-11 16:08:03

标签: java cron quartz-scheduler

我正在使用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);

这是每个月3日和18日23:00开火的cron时间表。例如,如果我今天(8月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 个答案:

答案 0 :(得分:32)

你真正想要直接使用CronExpression对象而不是CronTrigger。正如您所发现的那样,它不会计算过去的下一次运行时间......但是CronExpression会!

CronExpression的方法有:getNextValidTimeAfter。这就是你想要的。

答案 1 :(得分:4)

在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);

答案 2 :(得分:1)

CronTrigger.getFireTimeAfter()方法有一个保护机制,用于防止指定的时间过去。

这可以通过在您评估的过去时间调用setStartTime firth来规避。然后,对getFireTimeAfter的调用应返回有效结果。

答案 3 :(得分:0)

根据Quartz doc

  

在给定时间

之后返回CronTrigger下次触发的时间
“意志火”意味着“未来”。也就是说,CronTrigger下次触发时不会过去,并且不会返回过去的日期。

我不确切地知道你想要什么,但你晚上对这些方法感兴趣:

  • getPreviousFireTime():返回触发器上次触发的时间
  • getTimeBefore():返回触发器在给定日期之前触发的时间(在过去工作) - 注意:此处似乎暂时未实现

答案 4 :(得分:0)

这有点奇怪,但存在保护机制。不知道为什么Quartz Team有这个检查。仅当我向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);