[Funktion(en), Modul: Cal] Algorithmus für wiederkehrende Termine

Begonnen von k00ni, 12. September 2007, 15:23:25

Vorheriges Thema - Nächstes Thema

k00ni

Hallo,
ich grübel gerade an einem Algorithmus für wiederkehrende Termine. Wir \"hacken\" gerade das Cal-Modul und stellen es etwas um, deshalb. Ich hab nun nur noch keinen richtigen Ansatz für oben genanntes.
Man kann einen Termin erstellen und diesen als \"regelmäßig\" eintragen. Zusätzlich noch sagen, ob er bspw. \"jeden\" (jeden zweiten, jeden zweiten und dritten, usw.) Donnerstag stattfindet.
Beispielsweise:
 

- jeden Donnerstag
- jeden zweiten und dritten Samstag

 
 
Nun muss ich einen Algo finden, womit ich diese Termine in den Übersichten einbinden kann. Anbei, ich übergebe an die Funktion eine Begrenzung, in welchem Zeitraum diese liegen müssen. (Timestamps, von wann bis wann)
Mein Ansatz sieht so aus, dass ich mir die Eintragung bei \"regelmäßig\" (also bspw. \"jeden zweiten\" \"samstag\", getrennt voneinander gespeichert) anschaue und dann beim Wochentag die Nummer (1-7) ermittle. Dann aus den Angaben hochrechnen auf die direkten Timestamps und dann prüfen, ob sie in den aktuellen Zeitraum reinfallen. Soweit die Theorie /uploads/emoticons/icon_e_smile.gif.4a0acefcb917340d2c82e5239c009e6e.gif\" alt=\":)\" /> Vielleicht habt ihr die eine oder andere Idee.
 
Grüße
 - Editiert von k00ni am 14.09.2007, 18:50 -

Powie

Für jedes Vorkommen des \"wiederkehrenden\" Termins einen eigenen Datensatz generieren!
Dies hat später den Vorteil das man auch einzelne Instanzen dieses Termins löschen kann ohne den gesamten zu entfernen!

k00ni

Für jedes Vorkommen des \"wiederkehrenden\" Termins einen eigenen Datensatz generieren![/quote]
:ugly: Meinst du das ernst? Stelle mir das gerade etwas umständlich vor, wenn man da was an dem Termin ändern möchte. Da müsst ich ja dann alle x tausend Termine anpassen. Gut, dass könnte man umgehen, indem man eine zweite ID einführt und diese dann bei allen Terminen (die zusammengehören) gleich ist.
Dies hat später den Vorteil das man auch einzelne Instanzen dieses Termins löschen kann ohne den gesamten zu entfernen![/quote]
Nur wie stellst du dir dass dann mit der Administrierung vor? Bei uns geht ein Toptermin immer über 6 Monate. Das sind hochgerechnet 24 Wochen (4 Wochen = 1 Monat). Das sind ggf. 48 Einträge für einen Termin! Ok, der Vorteil wäre, dass man das Auslesen stark vereinfacht. Aber wie willst du dann alle Termine zusammenbekommen und anpassen, wenn Änderungen stattfinden. Man denke an die Art der Wiederkehrung, statt jeden Donnerstag nun jeden ersten und vierten Montag. Dies könnte man dann durch eine Sperrung der \"Regelmäßigkeit\" entgegensteuern, also dass man das nachhaltig nicht einstellen kann. *grübel*
Eigentlich gefällt mir der Vorschlag gut... aber mal schauen, was du zu oben geschriebenen meinst, Powie /uploads/emoticons/icon_e_smile.gif.4a0acefcb917340d2c82e5239c009e6e.gif\" alt=\":)\" />/uploads/emoticons/icon_e_biggrin.gif.1a84f5257b36e14b36d04985314f877f.gif\" alt=\":-D\" />
 
Nächtliche Grüße

mahe

Du setzt ein Flag \"Serientermin\".
Anhand davon kannst du dann unterscheiden obs ein einmaliger Termin ist oder nicht.
Die anderen Termine findest du anhand der eingegebenen Daten (müssen ja gleich sein)

http://blog.mahe.at\" rel=\"external nofollow\">http://blog.mahe.at/wp-content/uploads/2007/06/88x31_1.jpg\" alt=\"88x31_1.jpg\">


Ja, diese Signatur dient zur Werbung!


Und dass ich meine Posts wiederfinde ...


Powie

du hast die Lösung doch schon selbst angesprochen. Sobald es sich um einen Serientermin handelt generierst du eine eindeutige ID beim Eintragen in die DB, und diese ID ist dann bei allen der gleichen Serie die selbe. Ist es kein Serientermin steht keine ID drin.  /uploads/emoticons/icon_e_surprised.gif.a8707b3f35a569cb4cfe563fc72ef78d.gif\" alt=\":-o\" />

k00ni

Morgähnn... ,
hier mal ein paar erste Rümpfe, was ich die Tage so geschafft habe. Nicht viel, aber irgendwie hängen meine Gedanken grad bei 1000 Stellen gleichzeitig.
Wie dem auch sei. Der User kann beim Termin anlegen ja die Regelmäßigkeit bestimmen. Dies geht folgendermaßen im HTML-Code.
 


jeden
jeden ersten
jeden ersten und zweiten
jeden ersten und dritten
jeden ersten und vierten
jeden zweiten
jeden zweiten und dritten
jeden zweiten und vierten
jeden dritten
jeden dritten und vierten
jeden vierten
 

\'. $S_day .\'\'; $I_counter++;
} ?>

 
 
$A_days ist das Array aus der pcal_main.php, welches die Wochentage enthält. Hier wird jedem Wochentag gleich die richtige Nummer zugeordnet. (0-6)
Um dann beim Anlegen des Termins und wenn es ein regelmäßiger ist, alle weiteren anzulegen, hab ich folgendes:
 

 
Die Funktion check_which_week soll mir prüfen, in welcher Woche der übergebene Zeitstempel ist. Wie genau diese dann aussieht, muss ich mir noch überlegen. Wenn es gut läuft, hab ichs heute Abend.
[edit]Was ich mir auch noch überlegen muss, wie ich $_POST [\'S_periodic\'] abfragen kann. Denn es kann 0 enthalten, aber auch 14, was bedeutet, dass der Termin am ersten und vierten Montag (Beispiel) ist. Man könnte die Zahlfolge als Array sehen und dann Abfrage: $_POST [\'S_periodic\']
  • und $_POST [\'S_periodic\'] [1].[/edit]
     
    Grüße

Powie

ich kann dir nachfühlen. Kalender sind eine Welt für sich, und der pCal hat mich selbst schon unzählige male in den Wahnsinn getrieben.
Was genau programmierst du nun? Einen eigenen Kalender oder eine Änderung am pSys Kalender?  Wenn ich mir ansehe was du da machst, es kommt mir ein wenig \"übertrieben\" vor.

k00ni

Was genau programmierst du nun? Einen eigenen Kalender oder eine Änderung am pSys Kalender? Wenn ich mir ansehe was du da machst, es kommt mir ein wenig \"übertrieben\" vor.[/quote]
Wir bohren dein Kalender-Modul auf. Wir hatten u.a. vor, wiederkehrende Termine zu implementieren, neue Felder hinzufügen für Feste, Konzerte etc., neue Arten (Tagestermin, Termin des Monats) von Terminen einbauen sowie eine Implementierung, dass sich User für einen Termin einschreiben können und dies über ihr Userprofil angezeigt wird.
Zu sagen ist auch, dass bei uns der Kalender für Feste und Partys genutzt wird.

k00ni

Ich habs! Muhahaha. /uploads/emoticons/icon_e_surprised.gif.a8707b3f35a569cb4cfe563fc72ef78d.gif\" alt=\":-o\" />
Folgende Funktion ermittelt mir nun anhand eines Timestamps, in welcher Woche (1-5) eines Monats sich der Termin befindet.
 

 5) $I_real_week = 5;
return $I_real_week;
}
?>

 
 
Es geht bestimmt noch kleinerer, sauberer, kürzerer, besserer... :ugly: Aber hauptsache, dass Ding läuft erstmal. Nun muss ich nur noch die Abfragen anpassen und dann können die ersten Tests starten. Das Problem ist, dass unten im Beispiel die 1 und 2 bei der Abfrage variieren können. Es könnt auch 2, 5 sein. Damit bekommt man gesagt, in welchen Wochen des Monats der Termin an Tag X stattfindet.
 

if (get_week ($I_start_time) == 1 AND get_week ($I_start_time)  == 2)

 
 
Grüße

0 ist ein gültiger Zeitstempel. Deswegen ist es fashlc, 0 als \"nicht gesetzt\" zu behandeln. Dafür gibt es den Typen \"null\".

Es geht bestimmt noch kleinerer, sauberer, kürzerer, besserer...[/quote]
Natürlich: http://storage.cj-soft.de/php-functions/GetWeekOfMonth.func.php\" rel=\"external nofollow\">GetWeekOfMonth()

BTW: Wenn ich versuche, dein Skript zur Berechnung des 31. Dezember 2007 zu verwenden, bricht das Skript irgendwann mit einem Timeout ab. Vielleicht solltest Du das nochmal prüfen.
Ach ja: Mein Skript berechnet die Woche richtig: 6. Woche im Dezember.

k00ni

Ich wusste es, dass wieder einer besser ist /uploads/emoticons/icon_e_surprised.gif.a8707b3f35a569cb4cfe563fc72ef78d.gif\" alt=\":-o\" />
Ich habe mir mal ein paar Gedanken gemacht, wie man das noch angehen könnte, so ohne Schleife. Dabei könnte man es auch folgendermaßen machen:
Ein Monat ist ja mindestens 4 Wochen, maximal 6 Wochen lang. Daraus könnte man folgendes Bild erstellen (36-40 sind die Nummern der Wochen aufs Jahr bezogen; ca. 52 Wochen maximal glaub ich):
 

1. Woche: 36
2. Woche: 37
3. Woche: 38 (X)
4. Woche: 39
5. Woche: 40

 
 
Der übergebene Timestamp liegt in der Woche 3, Nummer 38.Man braucht da eigentlich nun nur noch folgendes rechnen:
40 - 36 = 4.
Da wir hier aber schon bei 36 die erste Woche haben, dass Ergebnis um 1 erhöhen. Also 5 (Gesamtanzahl der Wochen).
Nun rechnen wir folgendes:
40 - 38 = 2.
Damit haben wir nun die Differenz zwischen der Woche, in der der Timestamp liegt und der letzten Woche des Monats.
5 (Gesamtanzahl) - 2 (Differenz) = 3


Der übergebene Timestamp liegt in der dritten Woche des Monats. Das ist ein anderer Ansatz und ich weiß nicht, ob er auch sauber läuft (man denke an Winter und Sommerzeit). Aber eigentlich dürfte da nichts schiefgehen, da die Daten ja per date und mktime ermittelt werden und diese ja sehr präzise arbeiten.
 
UPDATE: Hier nun der zugehörige Quelltext (ungetestet):
 

 Letzte Woche - erste Woche + 1 = Gesamtanzahl Wochen; 
// > Letzte Woche - Timestamp-Woche = Differenz zur letzten Woche.
// --> Gesamtanzahl Wochen - Differenz zur letzten Woche = Nummer der Timestamp-Woche. (1-6)
return $I_last_week_in_month - $I_first_week_in_month + 1 - ($I_last_week_in_month - $I_timestamp_week);
}
?>

 
 
Die Ermittlung von $I_last_week_in_month ist etwas unschön. Nur wie will man sonst die letzte Woche sauber bestimmen? Problem ist hier der Februar und dass er bswp. im Schaltjahr 29 statt 28 Tage hat.

Aber eigentlich dürfte da nichts schiefgehen, da die Daten ja per date und mktime ermittelt werden und diese ja sehr präzise arbeiten.[/quote]
Das hat mit der Präzision von date und mktime nichts zu tun - die ist gegeben. Aber es ist so, dass man nicht einfach munter auf Timestamps addieren oder substrahieren kann, denn die Rückwandlung in ein Datum funktioniert dann nicht mehr zuverlässig.

Dein Skript weigert sich leider nicht, Daten für den 62 Februar 2004 zu berechnen.

all your base are belong to us