2009-10-10 21 views
30

Estoy buscando un patrón de estructura de datos para almacenar eventos recurrentes, pero todo lo que surgió daría como resultado una gran cantidad de manejo de casos especiales o la entrada del usuario y la recuperación de datos son demasiado complejas. (Tengo la clara sensación de que no he entendido el dominio del problema lo suficiente como para hacer esto).Estructura de datos para almacenar eventos recurrentes?

¿Cómo puedo almacenar eventos recurrentes al estilo de Outlook?

  • Cada día a las 8 am
  • Cada primer martes de un mes
  • Cada 1er diciembre por tres años
  • cada dos horas durante una semana
  • ...

Respuesta

16
No

Son varios documentos que describen estructuras de datos y algoritmos para este caso de uso. Además, puede ver el código o las descripciones de la implementación de código abierto de crontab y de Quartz (Java) o Quartz.NET (.NET).

Este es un tal papel

http://portal.acm.org/citation.cfm?id=359763.359801&coll=ACM&dl=ACM&CFID=63647367&CFTOKEN=55814330

Por ejemplo, las tiendas cron la información como esta (* significa que cada, por lo que un * bajo meses significa que cada mes)

 

.---------------- minute (0 - 59) 
| .------------- hour (0 - 23) 
| | .---------- day of month (1 - 31) 
| | | .------- month (1 - 12) OR jan,feb,mar,apr ... 
| | | | .---- day of week (0 - 6) (Sunday=0 or 7) OR sun,mon,tue,wed,thu,fri,sat 
| | | | | 
* * * * * 

There are several special entries, most of which are just shortcuts, 
that can be used instead of specifying the full cron entry: 

Entry  Description     Equivalent To 
@reboot Run once, at startup.  None 
@yearly Run once a year    0 0 1 1 * 
@annually (same as @yearly)   0 0 1 1 * 
@monthly Run once a month   0 0 1 * * 
@weekly Run once a week    0 0 * * 0 
@daily  Run once a day    0 0 * * * 
@midnight (same as @daily)   0 0 * * * 
@hourly Run once an hour   0 * * * * 

6
 
Event: 

StartDate 
EndDate (calculated on change of NumberOfOccurances) 
NumberOfOccurances (calculated on change of EndDate) 
Frequency e.g. 1/2hrs, 1/month, 1/day, .... 
CorrectionFunction e.g. first Tuesday, last Sunday, ... 

bool OccuresOn(day) 
Date NextOccurance(date) 
17

Compatible con el estándar iCalendar Tipos de eventos

El IETF poner algún pensamiento en esto cuando se creó el internet calendario y programación de especificación principal objeto, más conocido como iCalendar.

La especificación incluye la repetición del evento.

Como una ventaja adicional, su base de datos podrá compartir datos con otras fuentes de datos compatibles con iCalendar como los calendarios de Google y Apple.

http://tools.ietf.org/html/rfc5545

5

Aquí es mi opinión - por favor, hágamelo saber si me falta nada:

Sobre la base de las opciones de Outlook de recurrencia, que tiene una tabla con los campos necesarios regulares:

FieldName  DataType  Sample Data 
ID    int   primary key 
EventID   int   foreign key (to EventID from Event Table) 
StartTime  DateTime  8:00 AM 
EndTime   DateTime  8:30 AM 
Duration  int   30 (minutes) 
StartDate  DateTime  01/25/2014 
EndBy   DateTime  01/25/2024 
NoEndDate  bit   False 
NumOccurrences int   10 
RecurrenceType int   ****See below for instructions on how to use these last 6 fields 
Int1   int   
Int2   int 
Int3   int 
String1   nvarchar(50) 
IntYears  int 

Aquí es donde sucede la magia. esta lógica solo requiere 4 enteros y una cadena.

The month of year (1 = Jan, 12 = Dec), 
The day of the month (1 = the 1st, 31 = 31st), 
Day of the week (0 = Sunday, 1=Monday, 6= Saturday), 
Week of the month (1 = first, 4 = forth, 5 = last), 
Yearly reocurrence (1=1,2=2) 
When multiple days can be selected I use a comma delimited string (1,3,5 = Monday, Wed, Friday) 

entro los 3 números enteros en el orden en que aparecen en el programador de recurrencia perspectiva Cita, esto ahorra feilds adicionales, la lógica, la molestia. * Si abre al programador perspectiva cita, este será un poco más fácil de seguir:

The RecurrenceType field can be any of the 7 following choices 

(Hay 2 opciones para diario, mensual y anual, y una opción para la semana):

10 = Daily (Every `Int1` day(s))  
      Every  4 day(s) 
11 = Daily (Every Weekday) -- no variables needed 
      Every Weekday (MTWTF) 
20 = Weekly (Recur every `Int1` week(s) on: `String1` 
      Recur every  3 week(s) on Monday, Wednesday, Friday 
(`String1` will be a list of days selected (0=Sunday, 1=Monday, 2=Tuesday... 7=Saturday) so for (Mon, Wed, Fri) String1 would hold "1,3,5". You would parse this on the code side to pull the actual days.) 
30 = Monthly (Day `Int1` of every `int2' month(s) 
       Day 28 of every  2 month(s) 
31 = Monthly (The `Int1` `Int2` of every `Int3` month(s) 
       The forth Tuesday of every  1 month(s) 
40 = Yearly (Recur every `intYears` year(s) On `Int1` `Int2`) -- 
      Recur every   1 year(s) on Jan 28th 
41 = Yearly (Recur every `intYears` year(s) on the `Int1` `Int2` of `Int3`) -- 
      Recur every   1 year(s) on the forth Tuesday of January 

el código para tirar o guardar el reocurrence se vuelve bastante simple

if (RecurrenceType = 10) 
    Every `int1` days 
if (RecurrenceType = 11) 
    Every Weekday 
if (RecurrenceType = 20) 
    Every `int1 weeks on 
    parse `string1` and populate checkboxes for Mon, Tues, ... 
if (RecurrenceType = 30) 
    `int1 day of every `int2` month 

etc... 

Espero estar explicando esto lo suficiente. Avíseme si algo no está claro o si no funciona. Estoy construyendo esto para una aplicación actual. Gracias a todos.

+0

¡Hola! ¡Gran respuesta! Me deja con una pregunta abierta: ¿hay una manera rápida de calcular todas las fechas entre la fecha de inicio y la fecha de finalización, sin iterar cada fecha? –

Cuestiones relacionadas