Struktura danych do przechowywania powtarzających się zdarzeń?

Szukam wzorca struktury danych do przechowywania powtarzających się zdarzeń, ale wszystko, co wymyśliłem, spowodowałoby dużą liczbę obsługi specjalnych przypadków lub wprowadzania danych przez użytkownika i pobierania danych są zbyt skomplikowane. (Mam wyraźne wrażenie, że nie rozumiem domeny problemu wystarczająco dobrze, aby to zrobić.)

Jak Mogę przechowywać powtarzające się wydarzenia w stylu Outlooka?

  • codziennie o 8 rano
  • Każdy pierwszy wtorek miesiąca]}
  • Każdego 1 grudnia dla trzech lata
  • co dwie godziny w tygodniu
  • ...
Author: Daniel Rikowski, 2009-10-10

4 answers

Istnieją różne prace opisujące struktury danych i algorytmy dla tego przypadku użycia. Dodatkowo można zobaczyć kod lub opisy implementacji open source crontab oraz Quartz (Java) lub Quartz.NET (. NET).

To jest jeden taki papier

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

Na przykład cron przechowuje informacje w ten sposób (* oznacza każdy, więc * under month oznacza każdy miesiąc)


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

 16
Author: Vinko Vrsalovic,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-01-15 15:43:35

Obsługa standardowych typów zdarzeń iCalendar

IETF zastanowiło się nad tym, kiedy stworzyli Internet Calendaring and Scheduling Core Object Specification , lepiej znany jako iCalendar.

Specyfikacja zawiera powtarzanie zdarzeń.

Jako dodatkowy bonus, twoja baza danych będzie podatna na udostępnianie danych z innych źródeł danych zgodnych z iCalendar, takich jak kalendarze Google i Apple.

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

 17
Author: Mark Harrison,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-01-05 22:20:19
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)
 6
Author: Danny Varod,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-10-10 14:13:46

Oto moje ujęcie -- proszę dać mi znać, jeśli coś przeoczyłem:

Na podstawie opcji powtarzania programu Outlook, masz tabelę z wymaganymi polami:

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
Tutaj dzieje się magia. ta logika wymaga tylko 4 liczb całkowitych i jednego ciągu.
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)

Wprowadzam 3 liczby całkowite w kolejności, w jakiej pojawiają się w harmonogramie nawrotów spotkań programu outlook, oszczędza to dodatkowe wątki, logikę, irytację. *Jeśli otworzysz harmonogram appt programu outlook, to będzie nieco łatwiejszy do naśladowania:

The RecurrenceType field can be any of the 7 following choices 

(dostępne są 2 opcje dla dziennego, miesięcznego i rocznego oraz jedna opcja dla tygodniowego):

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

Kod do ściągnięcia lub zapisania reocurrence staje się dość prosty

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...
Mam nadzieję, że wyjaśniam to wystarczająco dokładnie. Daj mi znać, jeśli coś jest niejasne lub jeśli nie będzie działać. Buduję to dla bieżącej aplikacji. Dzięki wszystkim.
 5
Author: Dan B,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-01-28 22:06:23