2010-10-20 21 views
10

Estoy trabajando en una aplicación de tipo calendario Groovy/Java que permite al usuario introducir eventos con una fecha de inicio y una repetición opcional. Si se trata de un evento recurrente, que pueden repetirse:lógica evento recurrente

  • mensual de una fecha del mes que corresponda a la fecha de inicio
  • semanal en un día de la semana de la que corresponde a la fecha de inicio
  • cada 2 semanas en un día de la semana de la que corresponde a la fecha de inicio
  • etc.

que originalmente había planeado el uso de la API de Google Calendar para hacer toda la lógica de la repetición, pero resultó ser un enorme PITA , por razones Discutiré más si a alguien le importa.

Así que ahora, he decidido rodar mi propia solución. Dada una fecha, quiero averiguar si un evento recurrente ocurre en esta fecha. Mi lógica (en pseudocódigo) será la siguiente:

public boolean occursOnDate(def date, def event) { 

    def firstDate = event.startDate 

    if (firstDate > date) { 
    return false; 

    } else if (event.isWeekly()) { 
    return event.dayOfWeek() == date.dayOfWeek() 

    } else if (event.isMonthly()) { 
    return event.dayOfMonth() == date.dayOfMonth() 

    } else { 
    // At this point we know the event occurs every X weeks where X > 1 
    // Increment firstDate by adding X weeks to it as many times as possible, without 
    // going past date 
    return firstDate == date 
    } 
} 

Esta lógica parece razonable, pero en realidad será un buen montón de esfuerzo para poner en práctica si tenemos en cuenta todos los casos extremos extraño (por ejemplo, cómo manejar una mensual recurrente evento en febrero cuya primera aparición es el 31 de enero).

¿Hay una biblioteca que puede tomar me ayude a poner en práctica esto? Algunos detalles serían muy apreciados (por ejemplo, no se otorgará crédito por "Usar tiempo Joda").

Gracias, Don

+0

Pregunta similar: [¿Cuál es el mejor patrón de recurrencia calculadora de la fecha java] (http://stackoverflow.com/q/492055/642706) –

+0

Este documento Martin Fowler, [eventos periódicos para calendarios] (http://martinfowler.com/apsupp/recurring.pdf) podría ser útil. –

Respuesta

2

No sé nada de maravilloso, y mi primera sugerencia iba a ser Joda, pero se sabe sobre él.

Sé que esto puede parecer excesivo para usted, y tal vez incluso no aplicable, pero Quartz Scheduler maneja muy bien esta repetición y reglas relacionadas con los eventos. No puede usar sus capacidades de programación, y simplemente use las clases de Trigger (como CronTrigger) para calcular las fechas del evento para usted.

El enlace CronTrigger anterior muestra algunos ejemplos de expresiones que puede utilizar para manejar sus eventos, como esto particularmente desagradable situación: "? 0 0 12 L *"

- desencadenar un evento a mitad del día cada último día del mes (sin dolores de cabeza con años bisiestos y tal)

Se manejan también los problemas del horario de verano.

En cuanto al código, crear el gatillo con la repetición deseado y entonces es posible extraer todos los tiempos de cocción que desea:

Date firstFireTime = myTrigger.getNextFireTime(); 
... 
while (...) { 
    Date nextFireTime = myTrigger.getFireTimeAfter(previousFireTime); 
    ... 
} 

Hope esto puede ser útil.

+0

Si tiene información más específica sobre cómo puedo usar Joda/Quartz para lograr mi objetivo, me encantaría escucharlo. –

+0

Se agregó más información arriba :) – mdrg

8

El tipo de reglas de repetición que desee están razonablemente bien especificado en el RFC-2445 (básicamente, la especificación de iCal). Obtener las minucias de esto correcto puede ser bastante complicado. Me gustaría sugerir el uso de la biblioteca de la google-rfc-2445 para esta u otra aplicación de esa especificación como iCal4J.

0

No estoy muy familiarizado con la biblioteca de Groovy, pero como Groovy se está ejecutando en JVM, entonces supongo que también debería poder utilizar la biblioteca de Java/Scala.

Lo que necesita aquí es una biblioteca profesional de generación de cronogramas como Lamma (http://lamma.io) en lugar de una biblioteca de fecha y hora de uso general como Joda.

// monthly on a date of the month that corresponds to the start date 
    // output: [Date(2014,6,10), Date(2014,7,10), Date(2014,8,10), Date(2014,9,10), Date(2014,10,10)] 
    System.out.println(Dates.from(2014, 6, 10).to(2014, 10, 10).byMonth().build()); 

    // weekly on a day of the week of that corresponds to the start date 
    // output: [Date(2014,6,10), Date(2014,6,17), Date(2014,6,24), Date(2014,7,1), Date(2014,7,8)] 
    System.out.println(Dates.from(2014, 6, 10).to(2014, 7, 10).byWeek().build()); 

    // every 2 weeks on a day of the week of that corresponds to the start date 
    // output: [Date(2014,6,10), Date(2014,6,24), Date(2014,7,8)] 
    System.out.println(Dates.from(2014, 6, 10).to(2014, 7, 10).byWeeks(2).build()); 

    // edge cases are handled properly, for example, leap day 
    // output: [Date(2012,2,29), Date(2013,2,28), Date(2014,2,28), Date(2015,2,28), Date(2016,2,29)] 
    System.out.println(Dates.from(2012, 2, 29).to(2016, 2, 29).byYear().build()); 
Cuestiones relacionadas