Kalender mit Termin-Wiederholung

Einklappen
X
 
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

  • Kalender mit Termin-Wiederholung

    Hallo!

    Für unser Firmen-Intranet bastel ich gerade einen phpiCalendar Ersatz, der vom Aufbau her wesentlich einfacher daherkommt und an Apple iCal angelehnt ist. Allerdings komme ich bei der Termin-Wiederholung (alle X Tage, alle X Wochen, etc.) nicht weiter. Das ist mir irgendwie noch zu hoch

    Also... ich breche jetzt mal die Funktion auf die Basics herunter. Die Darstellung im Kalender erfolgt tageweise, d.h. der Tag mit Datum wird an eine Funktion übergeben, welche dann nachschaut ob Termine an diesem Tag stattfinden. Die Termine sind natürlich in der Datenbank mit Start und End-Datum vorhanden und evtl. die Angabe der Wiederholung (DAILY, WEEKLY, MONTHLY, YEARLY und INTERVAL).

    Die große Fragen also, wie kann ich nun errechnen, ob ein Termin an diesem Tag, den ich der Funktion übergeben habe, wiederholt wird?

    Sagen wir mal, ein Termine wurde von 3 Jahren eingetragen, der sich monatlich wiederholen soll. Das Start und Enddatum sind also quasi "3 Jahre alt". Ich müsste also an dem Tag für jeden wiederholenden Termin irgendetwas berechnen, damit ich weiss ob dieser sich heute wiederholt.

    Es wäre echt super, wenn mir irgendjemand einen Tipp oder Denkanstoß geben würde, wie ich das realisiere. Ich bräuchte nur das theoretische Wissen dazu.

    Also, besten Dank schonmal!

    Gruß!
    zipp0r

  • #2
    machs wie Outlook und trage alle ein:
    Jeder Termin bekommt ne Parent-ID, sodass du weißt, dass es einen Haupttermin aus der Serie gab.
    Dann erstellst du für das komplette Jahr oder alle 3 Jahre die Termine, also für jede Woche einen Termin.

    Bei Outlook ist das so ähnlich:
    Ich lege eine Serie an und es wird bis zum Enddatum in meinem angegebenen Interval ein Termin erzeugt, allerdings weiß ich nicht, wie er es macht, wenn es kein End Termin gibt.

    Du kannst aber auch einfach nur einen Termin erzeugen, mit einem Starttermin und dann den Interval angeben, z.B. jeden 2ten Dienstag.

    Dann speicherst du beim Erstellen, wann der 2te Dienstag ist und trägst das in eine gesonderte Spalte ein.
    Dein Script guckt jetzt immer, welches Datum in der zusätzlichen Spalte steht (z.B. 17.10.2006 wäre mal der 2te Dienstag).
    Dein Script geht nun bei, zeigt diesen Termin an und aktualisiert gleichzeitig das Datum in der gesonderten Spalte auf den nächsten Dienstag in 2 Wochen.
    Sunshine CMS
    BannerAdManagement
    Borlabs - because we make IT easier
    Formulargenerator [color=red]Neu![/color]
    Herkunftsstatistik [color=red]Neu![/color]

    Kommentar


    • #3
      gibt es eigentlich in php ein pendant zum DATE_ADD() in mysql?
      wäre auch mal interessant es über mysql zu lösen.

      andernfalls könntest du dir auch die timestamp-differenz eines intervalls ausgeben lassen, und somit prüfen bzw. festlegen, wann genau der wiederholungstermin jeweils ist...
      **********
      arkos
      **********

      Kommentar


      • #4
        Original geschrieben von arkos
        gibt es eigentlich in php ein pendant zum DATE_ADD() in mysql?
        strtotime()
        I don't believe in rebirth. Actually, I never did in my whole lives.

        Kommentar


        • #5
          stimmt. damit würd ich es machen...

          @wahsaga: hast du schon viel mit der mysql date_add() gearbeitet? sind damit überhaupt intervall-inserts möglich, oder ist es eine reine ausgabe- / select-funktion?
          **********
          arkos
          **********

          Kommentar


          • #6
            Original geschrieben von arkos
            hast du schon viel mit der mysql date_add() gearbeitet? sind damit überhaupt intervall-inserts möglich,
            Was soll denn ein "intervall-insert" sein?
            oder ist es eine reine ausgabe- / select-funktion?
            Es ist eine Datumsfunktion.
            I don't believe in rebirth. Actually, I never did in my whole lives.

            Kommentar


            • #7
              ich hab mal eine funktion geschrieben, die es "richtig" in die DB einträgt.

              die berechnungsfunktionen findest du hier:

              PHP-Code:
              function repeat($type$start$end) { //type=daily/weekly/2weekly/monthly_date/monthly_day/quarterly_date/quarterly_day - $start=yyyy-mm-dd hh-mm-ss - $end=yyyy-mm-dd hh-mm-ss/xx
                  
              $start_ts=strtotime($start);
                  if (
              $type=="daily" || $type=="weekly" || $type=="2weekly") {
                      switch (
              $type) {
                          case 
              "daily"$diff "86400"; break;
                          case 
              "weekly"$diff "604800"; break;
                          case 
              "2weekly"$diff "1209600"; break;
                      }
                      
              $a[0]=$start;
                      if (
              ereg("-"$end)) {
                          
              $end_ts strtotime($end);
                          
              $anz=intval(($end_ts-$start_ts)/$diff);
                      } else 
              $anz $end;
                      for(
              $i=1;$i<=$anz;$i++) {
                      
              $a[$i]=date("Y-m-d",$start_ts+$i*$diff);
                      }
                  } elseif (
              $type=="monthly_date" || $type=="monthly_day" || $type=="quarterly_date" || $type=="quarterly_day") {
                      if (
              ereg("-"$end)) $end strtotime($end);
                      else 
              $end $end+1;
                      
              $a[0] = $start;
                      
              $i 1;
                      while (
              $temp<$end) {
                          switch (
              $type) {
                              case 
              "monthly_date"
                                  
              $temp mktime(000date("m"$start_ts)+1date("d"$start_ts), date("Y"$start_ts)); 
                                  break;
                              case 
              "monthly_day":
                                  if (!(
              $i%3)) $temp mktime(000date("m"$start_ts), date("d"$start_ts)+35date("Y"$start_ts));
                                  else 
              $temp mktime(000date("m"$start_ts), date("d"$start_ts)+28date("Y"$start_ts));
                                  break;
                              case 
              "quarterly_date"
                                  
              $temp mktime(000date("m"$start_ts)+3date("d"$start_ts), date("Y"$start_ts)); 
                                  break;
                              case 
              "quarterly_day":
                                  
              $temp mktime(000date("m"$start_ts), date("d"$start_ts)+91date("Y"$start_ts));
                                  break;
                              default: 
              $temp mktime(000date("m"$start_ts)+1date("d"$start_ts), date("Y"$start_ts));
                          }
                          
              $start_ts $temp;
                          
              $a[$i] = date("Y-m-d"$temp);
                          
              $i++;
                          if (
              strlen($end)<=3$temp $i;    
                      }
                  } else die(
              "<span style='font-weight: bold; font-size: 12px; font-face: tahoma; color: red'>Error in function: repeat()</span>");
                  return 
              $a;

              Vielleicht hilft es was...

              Kommentar


              • #8
                Original geschrieben von wahsaga
                Was soll denn ein "intervall-insert" sein?
                OffTopic:

                ich gebe zu: es wäre eine art traum-funktion von mir:
                insert into kalender set date = date_add(begin,intervall,ende);

                ich denke, ist klar, wovon ich träume, oder
                man, wär das schön..

                klar wäre "add" somit falsch benannt...
                müsste evtl: date_flow_path() heißen.

                öh, kann man eigentlich wünsche an die mysql-entwickler-gemeinde richten??

                **********
                arkos
                **********

                Kommentar


                • #9
                  Danke für die Tipps bisher!

                  Alle Termine in die Datenbank einzutragen welche vorkommen können ist natürlich sehr uneffektiv - es muss ja irgendwann mal aufhören.

                  Die Sache mit der 2. Spalte wird auch nicht so einfach funktionieren, denn wenn ich im Kalender 6 Monate nach vorne springe, wird der Termin ja nicht angezeigt, weil der Termin in der 2. Spalte ja noch in der Vergangenheit liegt.

                  Ich vermute ich werde es so machen müssen, dass an dem Tag zu jedem Termine alle Wiederholungen berechnet werden müssen. Also vom Startdatum des Termins anfangen und bis zu dem Ende des Monats (wird ja komplett angezeigt) durchrechnen. Ich denke nicht das es so viele Wiederholer-Termine geben wird. Das müsste eigentlich schnell berechnet werden können.

                  Eine andere Möglichkeite sehe ich da eher nicht...

                  Kommentar


                  • #10
                    Tja, das mit den sich wiederholenden Terminen ist nicht einfach zu realisieren. Ich hab mir da auch schon einige Gedanken gemacht und bin noch zu keinem guten Ergebnis gekommen.
                    Du kannst dir ja mal den iCalendar RFC ansehen: http://www.ietf.org/rfc/rfc2445.txt - dort Abschnitt "4.3.10 Recurrence Rule". Das hilft einem allerdings auch nicht weiter.

                    Wenn es nur um so simple Dinge wie täglich, wöchentlich, monatlich usw. geht, dann lässt sich recht einfach überprüfen, ob ein Termin an einem bestimmten Tag stattfindet:
                    • täglich: Termin findet statt (an jedem Tag, trifft also immer zu)
                    • wöchentlich: aktueller Wochentag (Mo - So) muss mit Wochentag des Termins übereinstimmen
                    • monatlich: aktueller Tag des Monats (ungefähr 1 - 31) muss mit dem Tag des Monats aus dem Termin übereinstimmen
                    • jährlich: aktueller Monat (1 - 12) und aktueller Tag müssen jeweils mit dem Tag und dem Monat aus dem Termin übereinstimmen.
                    Du guckst dir also nicht das komplette Datum an sondern nur die relevanten Teile. Den aktuellen Tag kriegst du ja z.B. mit date('d').

                    Wenn die Bedingungen allerdings komplizierter werden (z.B. so wie bei iCalendar), dann muss man sich allerdings was Anderes einfallen lassen.
                    hopka.net!

                    Kommentar


                    • #11
                      ich meine, dass einsatz von Hopka zimmlich passend ist.
                      Vermutlich würde ich extra 4 tabellen machen
                      Taglich
                      termin_id

                      Wochentlich
                      termin_id | wochentag

                      Monatlich
                      termin_id | monatstag

                      jahrlich
                      termin_id | date

                      dann könnte man mit

                      select Termine.* from Wochentlich inner join
                      Termine on Termine.id=Wochentlich.termin_id
                      where wochentag=DATE_FORMAT(NOW() oder was auch immer,"%W")

                      UNION

                      select Termine.* from Monatlich inner join
                      Termine on Termine.id=Monatlich.termin_id
                      where monatstag=DAYOFMONTH(NOW() oder anderes)

                      UNION
                      und dasselbe mit Jahrlich.

                      der dauer von terminen kannst du mit to_days diferenz schnell rausfinden.
                      In jedem fall wird die suche nicht so lange dauern, da die wiederholende Termine jetzt nur in extratabellen stehen und werden dadurch viel schneller lokalisiert.
                      Slava
                      bituniverse.com

                      Kommentar


                      • #12
                        Öhm, du kannst doch auch nur eine Tabelle mit z.B. einem DATETIME Feld nehmen, und dann darauf die Datumsfunktionen anwenden.
                        Dann hast du Queries nach dem Schema:

                        SELECT * FROM termine WHERE (DATE_FORMAT(datum, '%w') = DATE_FORMAT(NOW(), '%w'))
                        UNION
                        ...
                        hopka.net!

                        Kommentar


                        • #13
                          ja das kann man machen, aber in diesem fall wird datenbank alle Datensätze untersuchen und zwar mit einer lästiger function
                          DATE_FORMAT(datum, '%w') = DATE_FORMAT(NOW(), '%w').

                          wenn man aber extra tabellen hat, dann wird die suche stark reduziert, und zwar nur auf Datensätze, die unserm suchkriterium entsprechen können.
                          ausserdem wird ein feld für bezeichnung von wiederholten Terminen, der bei einmaligen Terminen einfach leer bleibt gespart.
                          Slava
                          bituniverse.com

                          Kommentar

                          Lädt...
                          X