2009-10-10 8 views
30

Je suis à la recherche d'un modèle de structure de données pour stocker des événements récurrents, mais tout ce que j'ai fait aboutirait à un nombre élevé de cas spéciaux ou d'entrées utilisateur et de récupération de données trop complexes. (J'ai le sentiment distinct, que je n'ai pas assez bien compris le domaine du problème pour le faire.)Structure de données pour stocker des événements récurrents?

Comment puis-je stocker des événements récurrents de style Outlook?

  • Tous les jours à 8 heures
  • Chaque premier mardi dans un mois
  • Chaque 1er Décembre pour trois ans
  • Toutes les deux heures pendant une semaine
  • ...

Répondre

16

Il Divers articles décrivent des structures de données et des algorithmes pour ce cas d'utilisation. En outre, vous pouvez voir le code ou les descriptions de l'implémentation Open Source de crontab et de Quartz (Java) ou (.NET).

Ceci est un tel papier

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

Par exemple, les magasins Cron les informations comme celui-ci (* signifie tout, donc un * en mois signifie que chaque mois)

 

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

Prise en charge de la norme iCalendar types d'événements

L'IETF mettre une certaine pensée dans ce quand ils ont créé l'Internet et planification de base Calendaring Objet Spécification, mieux connu sous le nom iCalendar.

La spécification inclut la récurrence d'événement. En outre, votre base de données sera susceptible de partager des données avec d'autres sources de données compatibles avec iCalendar, telles que Google et les calendriers Apple.

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

5

Voici mon opinion - s'il vous plaît laissez-moi savoir si je manque quelque chose:

En fonction des options d'Outlook Récurrence, vous avez une table avec les champs réguliers nécessaires:

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 

Voici où la magie se produit. cette logique nécessite seulement 4 entiers et une chaîne.

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) 

I entrer les 3 entiers dans l'ordre où ils apparaissent dans les perspectives de rendez-vous planificateur Récurrence, cela permet d'économiser feilds supplémentaires, la logique, l'ennui. * Si vous ouvrez le planificateur appt de perspectives, ce sera un peu plus facile à suivre:

The RecurrenceType field can be any of the 7 following choices 

(Il y a 2 options pour tous les jours, mensuels et annuels, et une option pour la semaine):

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 

le code pour tirer ou enregistrer le reocurrence devient assez 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... 

J'espère que j'explique cela assez complètement. Faites-moi savoir si quelque chose n'est pas clair ou si cela ne fonctionnera pas. Je construis ceci pour une application actuelle. Merci à tous.

+0

Hey! Très bonne réponse! Il me laisse avec une question ouverte: Y at-il un moyen rapide de calculer toutes les dates entre la date de début et la fin par date, sans répéter chaque date? –

Questions connexes