language-agnostic design-patterns data-structures

language agnostic - Estructura de datos para almacenar eventos recurrentes?



language-agnostic design-patterns (4)

Estoy buscando un patrón de estructura de datos para almacenar eventos recurrentes, pero todo lo que surgió resultaría en un alto número de manejo de casos especiales o la entrada del usuario y la recuperación de datos son demasiado complejos. (Tengo la clara sensación de que no he entendido el dominio del problema lo suficientemente bien como para hacer esto).

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

  • Todos los días a las 8 a.m.
  • Cada primer martes en un mes
  • Cada 1 de diciembre por tres años
  • Cada dos horas durante una semana
  • ...

Aquí está mi opinión: por favor, avíseme si me falta algo:

En función de las opciones de recurrencia de Outlook, tiene una tabla con los campos regulares necesarios:

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)

Ingreso los 3 enteros en el orden en que aparecen en el planificador de periodicidad de citas de perspectiva, esto ahorra campos adicionales, lógica, molestia. * Si abre el planificador de citas de Outlook, esto 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 semanalmente):

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 extraer o guardar la repetición 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.


Hay 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 uno de esos papeles

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

Por ejemplo, cron almacena la información de esta manera ( * significa cada, por lo que a * debajo del mes significa todos los meses)

.---------------- 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 * * * *


Admite los tipos de eventos de iCalendar estándar

El IETF reflexionó sobre esto cuando crearon la especificación de calendarios y programación de objetos principales de Internet , mejor conocida 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


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)