Kalender / Termin DB

Einen Kalender bzw. eine Terminverwaltung mit Benutzerverwaltung kann auch eine Anwendung für eine Webseite sein. Realisiert ist diese für den Ruderklub Flensburg. Eine Beutzerverwaltung kann man machen, in diesem Beispiel wurde diese eingefügt: Ein User ist der Verwalter, alle anderen können sich frei Termine definieren bzw. neue User können sich Accounts anlegen, mit denen sie Terine anlegen können.

Der Kalender <Link> und zur Anmeldung <Link> um Termine zu Verwalten.

Angezeigt wird beim Kalender der aktuelle Monat, die Monate sind als Link hinterlegt. Eine Auswahl des Monats verzweigt in den etsprechenden Monat. Die Tage dens Monats (Kopfzeile) sind ebenfalls als Link hinterlegt, ein weiterer Klick bringt einen zur Tagesübersicht. Diese ist logischerweise von Null Uhr bis 24 Uhr aufgeteilt. Jede Stunde ist in 4 Teile aufgeteilt, eine feinere Einteilung ist möglich (im Programm vorgesehen). Damit kann man auf 15 Minuten genau den Termin im Tagesverlauf anzeigen lassen.
Ein Link auf den Eintrag (in der ersten Spalte) gibt bei Bedarf alle Daten zum Termin in ein extra Fenster (JavaScript) aus.

Die Tabelle terminacc für die Accounts der Termine enthält folgende Zellen:
# 0 Nr int(11) # 1 UID char(20) # 2 SID char(50) # 3 Passwd char(30) # 4 Bemerkung char(32)
Dabei ist "Nr" die laufende Nummer, "UID" das eingetragene Kürzel zum Account mit "Paswd" ale Kennwort. "SID" wird bei jeder Anmendung generiert und zur Auswertung genutzt um den gültig, angemeldeten Benutzer in seiner Session zu begleiten.

Die Tabelle "termin" für Termine besteht aus diesen Einträgen:
# 0 Nr int(10) # 1 UID char(20) # 2 Start date 0000-00-00 # 3 SZeit time 00:00:00 # 4 Ende date 0000-00-00 # 5 EZeit time 00:00:00 # 6 Wdh int(10) # 7 Intervall int(10) # 8 KurzDetail varchar (25) # 9 Details blob
Wiederholungen - Wie oft wird ein Termin Wiederholt.
Da gibts folgende Regelung: Es gibt max. 200 Wiederholungstermine, nur der esrte Termin bekommt die Daten, alle nachfolgenden den Wert "999".
Intervall - Der Abstand zwischen ersten und nächsten Termin
Da gib's folgende Regelung: Max. Wert 400, dieser Wert steht auch nur im ersten Termin. Die Wiederholungstermine bekommen die einen Wert der sich aus der Summe von 400 und der laufenden Nummer des ersten Termin bildet. So kann ich den ersten Wert immer wieder finden. So kann man entweder den Wiederholungstermin (alleine) verschieben oder auf den ersten Terminzurückgreifen und alle verschieben...

Es gibt 2 weiter Routinen die ähnlich sind wie "AnzeigeGesamtKal()". Die sind für die Ausgabe des Monats (mit Wochenenden besonders markiert) und des einzelnen Tages (Stunden sind aufgelöst in 15 Minuten "Schnipseln") zuständig.

 

############################################################################# function AnzeigeGesamtKal() { Global $Monate, $MonateAbk, $Monatstage , $aktTagJahr,$aktJahr, $aktMonat, $aktTag, $Schaltjahr, $Termin; $DatenAnzahl = count($Termin); $TermineNeu = array(array()); $MonatArr = array(); # verschiedene Darstellung der Monatsüberschriften $BGFarbe= " "; # Andere Hintergrudfarbe für aktuellen Monat # Anzeige Optimierbar, kleine Darstellung -> abgekürzte Überschriften $DehnFaktor = 1; # zum Vergrößern der Tabelle (Grafiken mal Dehnfaktor) if ($DehnFaktor >= 3) {$MonatArr = $Monate ;} if ($DehnFaktor == 2) {$MonatArr = $MonateAbk ;} if ($DehnFaktor == 1) { for ($i=0; $i < 12; $i++) {$MonatArr[$i] = $i+1 ;} } $TabBreite = (366 * $DehnFaktor) ; $ImageLeer = "<img src='l1x12.gif'>"; $ImageAktDatum = "<img src='hl1x12.gif'>"; $ImageTag = "<img src='t1x12.gif'>"; $heute = $aktTag . "." . $aktMonat . "." . $aktJahr; # Datum zusammenstellen $ImageTerminHeute = "<img src='h1x12.gif' border='0' alt='" . $heute . "'>"; for ($dehn=1; $dehn < $DehnFaktor; $dehn++) { $ImageTag = $ImageTag ."<img src='t1x12.gif'>"; $ImageLeer = $ImageLeer ."<img src='l1x12.gif'>"; $ImageTerminHeute = $ImageTerminHeute . "<img src='h1x12.gif' alt='" . $heute . "'>";
$ImageAktDatum = "<img src='hl1x12.gif'>"; } #Termine Datum umwandeln $DetailTermin = array(); # nimmt die Daten zum Termin auf, der im JavaSript, im extra Fenster angezeigt wird $k = 0; for ($d=0; $d<$DatenAnzahl; $d++) { if ($Termin[$d][6] <> "999") { $TermineNeu[$k][1] = $Termin[$d][1] ; $TermineNeu[$k][6] = $Termin[$d][6] ; $TermineNeu[$k][3] = $Termin[$d][3] ; $TermineNeu[$k][5] = $Termin[$d][5] ; $TermineNeu[$k][7] = $Termin[$d][7] ; $TermineNeu[$k][8] = $Termin[$d][8] ; $TagSE = BerechneStartEnde($Termin[$d][2],$Termin[$d][4]); $TermineNeu[$k][2] = $TagSE[0]; $TermineNeu[$k][4] = $TagSE[1]; $DetailTermin[$k] = Termininfo($Termin[$d]) ; $k++; } # Wiederholtermine (nur die Folgetermine) = 999 ignorieren. Die werden gesondert behandelt } $DatenAnzahl = count($TermineNeu); # TabelleHintergrund - Feld Grau echo "<TABLE width='" . $TabBreite . "' cellSpacing='1' cellPadding='0' border='0'>"; echo "<TBODY><TR><TD bgColor=#dcdcdc>"; # TabelleDaten - Ausgabe # erste Zeile - aktuller Monat hat andere Farbe, Monatsbeschriftung hat Link echo "<table width='" . $TabBreite . "' cellSpacing='1' cellPadding='0' border='0'>"; echo "<tr bgColor='#8DD1FA'><th><font size='-1'> ... </font></th>"; for ($i=0; $i<12; $i++) # Überschrift der 12 Monate { $NrMonat = $i + 1; if ($aktMonat == $NrMonat) { $BGFarbe= " bgcolor='#FFCC66'"; } # Aktuellen Monat farblich kennzeichenen else { $BGFarbe= " "; } echo "<th ". $BGFarbe . " width='". $Monatstage[$i]. "'><font size='-1'>" . LinkAuswahl("termine.php",$NrMonat,"AnzeigeMonat",$MonatArr[$i],"MonatAnzeigen") . "</font></th>"; } echo "</tr>"; # das war 1.For Schleife = Überschrift for ($i=0; $i<$DatenAnzahl; $i++) # für jeden Datensatz { $count = 1; echo "<tr bgcolor='#8DD1FA'>"; $ZeilenBeschriftung = $TermineNeu[$i][1] ; $Intervall = $TermineNeu[$i][7]; $Wiederholung = $TermineNeu[$i][6];

# $WdhCount = 0; echo "<td><nobr> <a href='javascript:InfoWin(\"" . $DetailTermin[$i]. "\")'>$ZeilenBeschriftung</a> &nbsp; </td>"; for ($j=0; $j<12; $j++) { $NrMonat = $j + 1; if ($aktMonat == $NrMonat) # aktuellen Monat mit andere Farbe hinterlegen { $BGFarbe= " bgcolor='#FFCC66'"; $ImageBG = $ImageAktDatum ; } else { $BGFarbe= " "; $ImageBG = $ImageLeer; } echo "<td " . $BGFarbe . " noWrap bgColor='#ffffff' width='". $Monatstage[$j]. "'><nobr>"; # Bilder wie Tage im Monat for ($img=0; $img < $Monatstage[$j]; $img++ ) { # Innerhalb Termin anderes Bitmap verwenden, $count zählt momentane Position (Tag) mit if (($TermineNeu[$i][4]>= $count) && ($TermineNeu[$i][2] <= $count)) { if ($count == $aktTagJahr) { echo "" . $ImageTerminHeute . ""; } else { echo "" . $ImageTag . ""; } } else { if ($count == $aktTagJahr) { echo "" . $ImageTerminHeute . ""; } else { echo "" . $ImageBG . ""; } } # Terminende wenn $count = $TermineNeu[$i][3] # Wiederholung > als der WdhCount dann Start + intervall u. Stop + intervall # so kommen die Wiederholungstermine in die gleiche Zeile wie der erste (Starttermin) if (($Wiederholung > 0) && ($count == $TermineNeu[$i][4])) { $diff = $TermineNeu[$i][4] - $TermineNeu[$i][2]; $TermineNeu[$i][2] = $TermineNeu[$i][2] + $Intervall ; $TermineNeu[$i][4] = $TermineNeu[$i][4] + $Intervall ; $Wiederholung--; } $count++; } echo "</td>"; } echo "</tr>"; } echo "</table>"; echo "</TD></TR></TBODY></TABLE><br>"; echo "Legende: Ein Tag = $ImageTag, aktuelles Datum = ". $ImageTerminHeute . $ImageTerminHeute ." <br>"; echo "Anzahl der Termine: $DatenAnzahl <br>"; echo "$Intervall - $diff " . $TermineNeu[7][1] . "..." . $TermineNeu[7][3] . " "; if ($TagSE[2] <> "OK") { echo " " . $TagSE[3]. " "; } } #############################################################################################

Ich mache kein Auswertung über das Datum, sondern berechne immer den laufenden Tag im Jahr. So gibt's weniger Streß beim Addieren (Wiederholungen) von Tagen. Dazu brauche ich Funktionen, die mir das in eine Richtung und in die andere Richtung berechnen:

 
# ------------------ Tag2Datum($TagImJahr,$Jahr)----------------------------
# Übergabe: Tag im Jahr, Rückgabe Datum im Format yyyy-mm-tt
# Das Format will die Datenbank
function Tag2Datum($TagImJahr,$Jahr)
 { $Monatstage= array("31","28","31","30","31","30","31","31","30","31","30","31");
   if ((ceil($Jahr / 4) == floor($Jahr / 4)) ) { $Monatstage[1] = $Monatstage[1] + 1; }
   $i = 0;
   $Tag = $TagImJahr;
   while ($Tag > $Monatstage[$i]) 
    { $Tag = $Tag - $Monatstage[$i];
	  $i++;
	}
   # Geht auf - der übergebene Tag war der letzte des Monats  	
   #if ($Tag == 0) {$Tag = $Monatstage[$i-1] ; }	
   $i++;
   $Datum = "" . $Jahr . "-" . $i . "-" . $Tag ;	
   return $Datum;
 }

# ------------------ Datum2Tag($Datum) ----------------------------
# Übergabe: Datum im Format yyyy-mm-tt
# Rückgabe: Tag des Jahres
function Datum2Tag($Datum)
 { $Monatstage= array("31","28","31","30","31","30","31","31","30","31","30","31");
   $Datumarray = explode("-",$Datum);
   if ((ceil($Datumarray[0] / 4) == floor($Datumarray[0] / 4)) ) 
    { $Monatstage[1] = $Monatstage[1] + 1; }

   $Tag = $Datumarray[2];      
   for($s=0; $s<($Datumarray[1]-1); $s++)
        { $Tag = $Tag + $Monatstage[$s]; }

   return $Tag; 
 }

Die Maximale Zahl der Tage im Jahr läßt sich auch festellen: Minimum sin dabei 365 Tage, Schaltjahre gibt es wenn das Jahr durch 4 teilbar ist: if ((ceil($Datumarray[0] / 4) == floor($Datumarray[0] / 4))) { "Tage + 1" }
Wenn das ergebnis beim auf und abrunden identisch ist (Jahreszahl/4), wird ein Tag zu 365 dazuaddiert.

Verwendungshinweis: Um das Script zu verwenden einfach diese Datei über den Browser speichern und dann mit einem Texteditor oder Dreamweaver / FirstPage etc. bearbeiten. Das Script darf für jeden frei verwendet werden, soweit der Autor / Quelle genannt wird. Wer nützliche Links / Scripte hat darf die mir auch gerne zur Verfügung stellen..