Jump to content
powie.de Tech Forum
Sign in to follow this  
k00ni

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

Recommended Posts

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 :) Vielleicht habt ihr die eine oder andere Idee.



Grüße

- Editiert von k00ni am 14.09.2007, 18:50 -

Share this post


Link to post
Share on other sites

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!

Share this post


Link to post
Share on other sites
Für jedes Vorkommen des "wiederkehrenden" Termins einen eigenen Datensatz generieren!


: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!


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 :):-D



Nächtliche Grüße

Share this post


Link to post
Share on other sites

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)

Share this post


Link to post
Share on other sites

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

Share this post


Link to post
Share on other sites

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'] [0] und $_POST ['S_periodic'] [1].[/edit]



Grüße

Share this post


Link to post
Share on other sites

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.

Share this post


Link to post
Share on other sites
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.


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.

Share this post


Link to post
Share on other sites

Ich habs! Muhahaha. :-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

Share this post


Link to post
Share on other sites
Guest

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

Share this post


Link to post
Share on other sites
Guest

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.

Share this post


Link to post
Share on other sites

Ich wusste es, dass wieder einer besser ist :-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.

Share this post


Link to post
Share on other sites
Guest
Aber eigentlich dürfte da nichts schiefgehen, da die Daten ja per date und mktime ermittelt werden und diese ja sehr präzise arbeiten.

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.

Share this post


Link to post
Share on other sites
Guest

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

Share this post


Link to post
Share on other sites
Die Ermittlung von $I_last_week_in_month ist etwas unschön. Nur wie will man sonst die letzte Woche sauber bestimmen?


Könnte man das nicht mit strtotime () umgehen? Gibts da die Möglichkeit mit etwas wie "last day in month" oder ähnlichen, sich den letzten Tag ermitteln zu lassen?



Grüße

Share this post


Link to post
Share on other sites
Guest
Wo könnte man das abfangen oder wo liegt der Fehler?

Schau dir meinen Quelltext an. Ich prüfe, ob der Parameter int ist, größer als -1 und in ein echtes Datum gewandelt werden kann.

Share this post


Link to post
Share on other sites
Guest
Könnte man das nicht mit strtotime () umgehen? Gibts da die Möglichkeit mit etwas wie "last day in month" oder ähnlichen, sich den letzten Tag ermitteln zu lassen?

Nein, das kann strtotime leider nicht.

Share this post


Link to post
Share on other sites
Guest

Finde ich nicht. Schon in der index.php sind mir diverse Stelen im Code aufgefallen, die potenziell gefährlich sind.

 

jeschkec@hulsten:~/projekte/calendar$ grep -R -c eval * | awk -F: '{sum+=$2} END { print sum}'
893

Spricht auch nicht für das Skript.

Share this post


Link to post
Share on other sites
Guest

Ich habe mir mehr andere Dateien genauer angesehen. Aber danke für den Hinweis, Statler! :H:

Share this post


Link to post
Share on other sites

jeschkec@hulsten:~/projekte/calendar$ grep -R -c eval * | awk -F: '{sum+=$2} END { print sum}' 
893

 

:ugly: Was bedeutet das ?

Share this post


Link to post
Share on other sites
Guest
Was bedeutet das ?

Dass in der Applikation ca. 900 mal eval() aufgerufen wird (bei 5000 Zeilen Code ist das ein eval in ca. jeder 5. Zeile). In Anbetracht der sonstigen Qualität des Quellcodes würde ich darauf tippen, dass man irgendwo unbehandelten Code ausführen kann. Man sollte bei eval() genau wissen, was man tut. Diesen Eindruck habe ich nach einer groben ersten Sicht aber nicht.

Share this post


Link to post
Share on other sites

Ich habe gerade bei der Arbeit mit dem pCal einen netten Codeschnipsel gefunden.Folgender Code ermittelt mir die Gesamtanzahl der Tage eines Monats.

 

// Anzahl der Tage des Monats ermitteln.
$days_month     = date("t", mktime(0,0,0,$month,1,$year));

 

Ich habe die Abfrage, obs ein richtiges Datum ist und den Code vom Powie ausm pCal mal in einer angepassten Funktion kombiniert.

 

 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);
}
?>

 


Grüße

Share this post


Link to post
Share on other sites
Guest
You are commenting as a guest. If you have an account, please sign in.
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Sign in to follow this  

×