2009-10-10 14 views
30

Poszukuję wzorca struktury danych do przechowywania powtarzających się zdarzeń, ale wszystko, co wymyśliłem, spowodowałoby dużą liczbę specjalnych przypadków obsługi lub wprowadzanie danych przez użytkownika i pobieranie danych jest zbyt skomplikowane. (Mam wrażenie, że nie rozumiem wystarczająco dobrze domeny problemu, aby to zrobić.)Struktura danych do przechowywania wydarzeń cyklicznych?

Jak mogę przechowywać wydarzenia cykliczne w stylu Outlooka?

  • Codziennie o 8 rano
  • Każdy pierwszy wtorek w miesiącu
  • Każdego 01 grudnia przez trzy lata
  • co dwie godziny na tydzień
  • ...

Odpowiedz

16

Nie są różne artykuły opisujące struktury danych i algorytmy dla tego przypadku użycia. Ponadto można zobaczyć kod lub opisy implementacji open source: crontab i Quartz (Java) lub Quartz.NET (.NET).

Jest jeden taki papier

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

Na przykład sklepy cron informacje tak (* oznacza każdy, więc * pod miesiącu 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 * * * * 

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

Obsługa standardu iCalendar Typy zdarzeń

IETF umieścić kilka myśli do tego, kiedy stworzył Internet kalendarzy i harmonogramów rdzenia Obiekt Specyfikacja, lepiej znany jako iCalendar.

Ta specyfikacja obejmuje powtarzanie zdarzeń.

Dodatkową korzyścią będzie udostępnianie bazy danych w innych źródłach danych zgodnych z iCalendar, takich jak kalendarze Google i Apple.

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

5

Oto moje zdanie - proszę dać mi znać, jeśli czegoś mi brakuje:

oparta na opcji Outlook nawrotu, masz tabelę z regularnych wymagane pola:

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 

Oto, gdzie 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) 

I wprowadzić 3 liczb całkowitych w kolejności, w jakiej pojawiają się w Outlook Powołanie Powtarzanie scheduler, oszczędza dodatkowych feilds, logika, rozdrażnienie. * Jeśli otworzysz do terminarza perspektywy APPT, to będzie nieco łatwiejsze do naśladowania:

The RecurrenceType field can be any of the 7 following choices 

(Są 2 opcje dziennym, miesięcznym i rocznym oraz jedna opcja za tydzień):

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 ciągnąć lub zapisać reocurrence staje się dość prosta

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śnię to wystarczająco dokładnie. Daj mi znać, jeśli coś jest niejasne lub nie działa. Buduję to dla bieżącej aplikacji. Dziękuje za wszystko.

+0

Hej! Świetna odpowiedź! Pozostawia mi jedno otwarte pytanie: czy istnieje szybki sposób obliczania wszystkich dat między datą początkową a końcową według daty, bez powtarzania każdej daty? –

Powiązane problemy