2011-08-11 12 views
15

Estoy usando el recurso Quartz CronTrigger para analizar series de formato cron schedule para determinar cuándo debe ejecutarse un trabajo específico. Sin embargo, en realidad no estoy usando Quartz para programar el trabajo.Quartz CronTrigger - Obteniendo el siguiente tiempo de disparo

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 indicada. Esto funciona bien cuando la fecha suministrada es ahora o en el futuro. Pero no parece funcionar si la fecha está 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); 

Cuál es un horario de cron para disparar a las 23:00 el 3 y 18 de cada mes. Así, por ejemplo, si hiciera esto hoy (11 de agosto), que 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 fijo la fecha de referencia al pasado, me da lo mismo la próxima vez el fuego.

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

que estaba esperando que la salida sea:

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

es el método no destinada a funcionar de esa manera o estoy haciendo algo mal?

Gracias!

+1

3 ª AUG está en el pasado. – Kal

+0

@Kal - sí, lo sé. Estoy tratando de averiguar cuándo el disparador se habría disparado después de la fecha indicada, incluso si ya ha pasado. – cambo

Respuesta

27

lo que realmente quiere utilizar el objeto de la CronExpression directamente no la CronTrigger. Como descubriste, 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.

+0

¡Sí! ¡Eso es exactamente lo que estoy buscando! ¡Gracias! – cambo

+0

¿Hay alguna manera de encontrar todas las ocurrencias dentro de un rango de fecha y hora? –

+0

@ManikArora: puede hacer un bucle while invocando getNextValidTimeAfter pasando primero como parámetro la fecha de inicio y luego todas las marcas de tiempo devueltas en cada iteración, y realiza un bucle mientras esas marcas de tiempo son aún menores que la hora de finalización. En cada iteración puede agregar las fechas resultantes a la lista de ocurrencias. – cvacca

0

De acuerdo con la Quartz doc:

devuelve el siguiente momento en el que se disparará el CronTrigger, después del tiempo establecido

"disparará" implica "en el futuro". Es decir, la próxima vez que se active el CronTrigger no está en el pasado, y las fechas en el pasado no se devuelven.

No sé exactamente lo que está tratando de acheieve, pero la noche estaría interesado en esos métodos:

  • getPreviousFireTime(): Devuelve la última vez que el gatillo se disparó
  • getTimeBefore() : Devuelve el momento en que el trigger se disparó antes de una fecha determinada (funciona en el pasado) - Nota: éste parece ser sin aplicarse por ahora
+0

Estoy tratando de usar el CronTrigger para saber si ha ocurrido una cierta "fecha de vencimiento". Las dos piezas de información que tengo son la "última fecha de vencimiento" y el cronograma cron. Entonces, lo que quiero hacer es getFireTimeAfter (lastDueDate) para decirme si ya he pasado la fecha de vencimiento actual. Parece que getTimeBefore() puede ser lo que estoy buscando, lástima que aún no se haya implementado. – cambo

1

El método CronTrigger.getFireTimeAfter() tiene un mecanismo de protección para evitar que el tiempo pasado especificado esté en el pasado.

Esto se puede eludir llamando al setStartTime firth con el tiempo que está evaluando. Luego, la llamada a getFireTimeAfter debe regresar con un resultado válido.

0

Esto es un poco extraño, pero existe el mecanismo de protección. No tengo idea de por qué el Equipo de Cuarzo tiene ese control.La prueba pasa a continuación sólo si añado una hora a la 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); 
3

En primavera se 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);