ABC_Mann: nächsten drei Montage ab heute

Moin,

ich möchte mit meinem Skript die nächsten 3 Montage und Mittwoche bestimmen. Bis letzte Woche hat es gut funktioniert, nun bei einem Monatsübergang gehts nicht mehr :-(. ich habs mit mktime + soundsoviel days versucht, aber er bleibt immer im aktuellen monat. Muss ich dann nochmal etwa überprüfen, ob er die "monatsgrenze überschreitet" und dann + 1 month miteinbringen?

Das Skript sieht bisher folgendermaßen aus:

//------ naechten drei Montage und Mittwoche erzeugen ---------------

function ntday($nr, $tt)  // naechsten montag und mittwoch bestimmen
  {
  for($i = 0 + $nr; $i < 7 + $nr; $i++)
  {
  $j = date('Y');
  $m = date('m');
  $d = date('d', strtotime("+ $i days"));
  $tag = date("d.m.Y",mktime(0,0,0,$m,$d,$j));
  $wt = date('w',mktime(0,0,0,$m,$d,$j));
  if($wt == $tt)
   {
   $training = $tag;
   }
  }
  return $training;
  }

$monday1 =  ntday(0,1);
$wednesday1 =  ntday(0,3);
$monday2 =  ntday(7,1);
$wednesday2 =  ntday(7,3);
$monday3 =  ntday(14,1);
$wednesday3 =  ntday(14,3);

//-------------------------------------------------------------------

Grüße und so

  1. Hallo,

    Muss ich dann nochmal etwa überprüfen, ob er die "monatsgrenze überschreitet" und dann + 1 month miteinbringen?

    Ja, genau das musst du bei deinem Script, man kann das ganze aber sicher auch einfacher lösen...

    gLan

  2. Ich würds ja anders (einfacher machen):

    1. überprüfen ob heute schon der gesuchte Tag ist (mittels date("w")
    2. wenn nein, dann zählst du zu aktuellen timestamp einfach so oft 86400 (=alle Sekunden eines Tages) dazu bis du den geuschten Tag erreicht hast (also wenn heute Donnerstag (5) ist und du Montag (1, + 7 weil in der nächsten Woche) suchst ... aktueller TS + (1+7-5)*86400
    3. aus dem errechneten Timestamp das Datum erstelln

    1. Nach der Antwort von Sven (strtotime('nextMonday')) ist meine Antwort hinfällig.

      Gar nicht gewusst was strtotime alles kann.

      mfg

      1. Moin!

        Nach der Antwort von Sven (strtotime('nextMonday')) ist meine Antwort hinfällig.

        Gar nicht gewusst was strtotime alles kann.

        Bleibt als einzige Frage nur noch: Ist "nächster Montag" der Montag in sieben Tagen, oder der am heutigen Tag, wenn heute Montag ist? :)

        Diesen Fall muss man natürlich entscheiden und evtl. abfangen. Ich vermute mal, strtotime() würde den Montag in 7 Tagen liefern.

        ...(spielerei auf der Kommandozeile)...
        Hm, tatsächlich kennt strtotime auch 'this Monday' und liefert dafür entweder das Datum von heute, oder das Datum des nächsten zukünftigen Montags (getestet heute mit "Donnerstag").

        - Sven Rautenberg

  3. Moin!

    Moin,

    ich möchte mit meinem Skript die nächsten 3 Montage und Mittwoche bestimmen. Bis letzte Woche hat es gut funktioniert, nun bei einem Monatsübergang gehts nicht mehr :-(. ich habs mit mktime + soundsoviel days versucht, aber er bleibt immer im aktuellen monat. Muss ich dann nochmal etwa überprüfen, ob er die "monatsgrenze überschreitet" und dann + 1 month miteinbringen?

    Das Skript sieht bisher folgendermaßen aus:

    Hier erzeugst du nacheinander:

    $j = date('Y');

    Das Jahr von HEUTE,

    $m = date('m');

    den Monat von HEUTE,

    $d = date('d', strtotime("+ $i days"));

    den Tag von HEUTE plus $i Tage.

    $tag = date("d.m.Y",mktime(0,0,0,$m,$d,$j));

    Und dann erzeugst du aus der Sammlung dieser Dinge ein neues Datum.

    Warum erzeugst du nicht in EINEM Schritt einfach das Tagesdatum von HEUTE plus $i Tage?

    strtotime() gibt dir einen Unix-Timestamp zurück von der Datumsbeschreibung, die in dem String steht. Wenn in dem String steht "HEUTE plus $i Tage", dann ist das Ergebnis schon ein vollwertiges Datum mit Tag, Monat und Jahr, und muss einfach nur noch durch die Funktion date() in eine menschenlesbare Form gebracht werden.

    Deine Einzelbehandlung von Jahr, Monat, anderem Tag und das durchschleifen durch mktime() verursacht dir den Fehler, dass das Resultat falsch ist, wenn zwar das Tagesdatum im neuen Monat liegt, aber das Monats- und Jahresdatum noch nicht.

    Abgesehen davon kann man die Wochentagsfindung auch noch optimieren. strtotime() kennt auch Befehle wie "next Monday" und findet dann ganz automatisch den nächsten Montag. Und mit Sicherheit auch den Montag in zwei und drei Wochen. Somit musst du nicht mehr einfach 7 Tage erzeugen und checken, welcher davon der Montag ist.

    $monday1 = date("d.m.Y", strtotime('next Monday'));

    - Sven Rautenberg

  4. Moin,

    ich möchte mit meinem Skript die nächsten 3 Montage und Mittwoche bestimmen.

    Ich würde den nächsten Montag/Mittwoch aufgrund Sekunden bestimmen, dann sind Monats-, Jahreswechsel und Schaltjahre kein Problem (wenn heute Montag ist, wäre das der erste Treffer):

    $jetzt = time();
    while ( date( "D", $jetzt ) != 'Mon' ) $jetzt += 3600*24; // +24 Std.
    $mon1 = date( "d.m.Y", $jetzt );
    $mit1 = date( "d.m.Y", $jetzt+3600*24*2 ); // +2 Tage
    $mon2 = date( "d.m.Y", $jetzt+3600*24*7 ); // +7 Tage
    ...

    Kalle

    1. Mein Vorschlag hat einen Denkfehler.

      Wenn heute Dienstag ist, finde ich zwar den nächsten Montag (wegen while), aber der daraus abgeleitete Mittwoch ist der übernächste.

      Also pro Wochentag eine eigene while-Schleife nehmen.

      Kalle

  5. (Hallo|Hi(ho)|Mahlzeit) ABC_Mann,

    für Fälle, in denen strtotime() versagt, weil das Datum außerhalb des Timestamp-Bereiches liegt,
    kannst du auf die Julianische Tagesnummer (auch Julianisches Datum, Julian Day Number) zurückgreifen.
    Aus der lässt sich leicht der passende Wochentag bestimmen.
    Monatsgrenzenprobleme lösen sich damit in Luft auf:

      
    function jdn_next_weekday(  
      $jdn, /// JDN des Basis-Datums  
      $weekday_wanted /// Wochentagsnummer (0...6) des gewünschten nächsten Wochentags  
    ) {  
      $current_weekday = ($jdn + 1) % 7; // Wochentag des Basisdatums  
      if ($current_weekday >= $weekday_wanted) {  
        // Wochentag des BD liegt nach dem gewünschten Wochentag  
        // (oder ist am gleichen Tag)  
        $jdn_wanted = $jdn - $current_weekday + 7; // JDN des nächsten Sonntags  
      }  
      else {  
        // Wochentag des BD liegt vor dem gewünschten Wochentag  
        $jdn_wanted = $jdn - $current_weekday;  // JDN des vorherigen Sonntags  
      }  
      $jdn_wanted += $weekday_wanted; // Sonntag (== 0) + gewünschter Wochentag  
      return $jdn_wanted; // JDN des gewünschten nächsten Wochentages  
    }  
    
    

    Lesetipps:
    * PHP-Kalenderfunktionen
    * gregorianToJD()
    * cal_from_jd()

      
    // Test  
    $test = array (  
      array (2009, 6, 18),  // THU  
      array (2009, 6, 21),  // SUN  
      array (2009, 6, 23),  // TUE  
    );  
      
    // Gewünschte Wochentagsnummer  
    $day_in_week_wanted = 1; // SUN: 0, MON: 1, ... WED: 3, ...  
      
    foreach ($test as $date_array) {  
      list ($year, $month, $day_in_month) = $date_array;  
      
      // JDN des Basis-Datums berechnen  
      $jdn = gregoriantojd($month, $day_in_month, $year);  
      // JDN des nächsten gewünschten Wochentags berechnen  
      $next_jdn_wanted = jdn_next_weekday($jdn, $day_in_week_wanted);  
      
      // Datums-Array des gewünschten nächsten Wochentags  
      $cal_next = cal_from_jd($next_jdn_wanted, CAL_GREGORIAN);  
      print_r($cal_next);  
      
      // nur zum Vergleich: das Datums-Array des Basisdatums  
      $cal_today = cal_from_jd($jdn, CAL_GREGORIAN);  
      print_r($cal_today);  
    }
    

    Weitere folgende Wochentage erhältst du, indem du für jede Woche 7 zur jeweiligen Tagesnummer addierst.

    MffG
    EisFuX

  6. moinsen,

    danke für die schnellen antworten. Habs jetzt ganz einfach, wie von sven inspiriert gemacht. Hat sich jetzt also erledigt.
    Für die die es interessiert:

    $monday1 =  date("d.m.Y", strtotime('next Monday'));
    $wednesday1 =  date("d.m.Y", strtotime('next Wednesday'));
    $monday2 =  date("d.m.Y", strtotime('next Monday') + (7 * 24 * 60 * 60));
    $wednesday2 =  date("d.m.Y", strtotime('next Wednesday') + (7 * 24 * 60 * 60));
    $monday3 =  date("d.m.Y", strtotime('next Monday') + (14 * 24 * 60 * 60));
    $wednesday3 =  date("d.m.Y", strtotime('next Wednesday') + (14 * 24 * 60 * 60));