mkyong - quartz java example
CronTrigger de cuarzo-Obtención del siguiente tiempo de disparo (5)
El método CronTrigger.getFireTimeAfter()
tiene un mecanismo de protección para evitar que el tiempo específico especificado esté en el pasado.
Esto se puede sortear llamando a setStartTime
firth con el tiempo en el pasado que está evaluando. Luego, la llamada a getFireTimeAfter
debería regresar con un resultado válido.
Estoy usando la función CronTrigger de Quartz para analizar las cadenas de formato de programación cron para determinar cuándo se debe ejecutar un trabajo específico. Sin embargo, no estoy usando Quartz para programar el trabajo.
Hay un método en CronTrigger llamado getFireTimeAfter (Date) que da la próxima vez que el trabajo se activará después de la fecha dada. Esto funciona bien cuando la fecha suministrada es ahora o en el futuro. Pero no parece funcionar si la fecha es en el pasado.
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);
Que es un cron cron para disparar a las 23:00 el 3 y 18 de cada mes. Entonces, por ejemplo, si hice esto hoy (11 de agosto), veo:
Reference time: Thu Aug 11 10:04:25 MDT 2011
Next fire after reference time: Thu Aug 18 23:00:00 MDT 2011
Pero si establezco la fecha de referencia en el pasado, me da el mismo tiempo de disparo siguiente.
Reference time: Wed Dec 31 17:00:00 MST 1969
Next fire after reference time: Thu Aug 18 23:00:00 MDT 2011
Esperaba que la salida fuera:
Reference time: Wed Dec 31 17:00:00 MST 1969
Next fire after reference time: Wed Aug 3 23:00:00 MDT 2011
¿El método simplemente no tiene la intención de funcionar de esa manera o estoy haciendo algo mal?
¡Gracias!
En Spring puede seguir el mismo enfoque que utilizan en sus pruebas de integración. 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);
Esto es algo raro pero el mecanismo de protección existe. No tengo idea de por qué el equipo de cuarzo tiene ese cheque. La siguiente prueba pasa solo si agrego una hora al 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);
Lo que realmente quiere usar el objeto CronExpression directamente, no el CronTrigger. Como descubrió, no calculará los próximos tiempos de ejecución en el pasado ... ¡pero CronExpression lo hará!
CronExpression tiene el método: getNextValidTimeAfter. Esto es lo que quieres.
Según el documento de cuarzo :
Devuelve la próxima vez que el CronTrigger disparará, después del tiempo dado
"Will fire" implica "en el futuro". Es decir, la próxima vez que el CronTrigger
se dispare no es en el pasado, y las fechas en el pasado no se devuelven.
No sé exactamente qué es lo que estás tratando de lograr, pero quizás te interesen esos métodos:
- getPreviousFireTime (): devuelve la última vez que se disparó el disparador
- getTimeBefore (): devuelve la hora en que se activó el activador antes de una fecha determinada (funciona en el pasado) - Nota: este parece no estar implementado por ahora