Tanja: Datum: wieviele Monate Unterschied?

hi,
 könnt Ihr mir bitte helfen.
Habe 2 timestamps, $t_alt und $t_neu.
wie kann ich nun feststellen, wieviel monate zwischen den beiden timestamps unterschied sind? jahresübergreifend wäre auch noch geschickt...
Danke

    1. was in deinem "siehe hier" nicht drin steht ist die wunderschöne mysql funktion timediff, sofern es um timestamps aus mysql geht

      beispielsweise select TIME_TO_SEC(timediff(ende,start)) from zeiten

      ich liebe mysql ;)

      und wenn es darum geht zu wissen, ob es genau einen monat ist, kannst du ja auch 2 sachen abfragen

      beispiel:

      select TIME_TO_SEC(timediff(ende,start)) as genauer_unterschied, TIME_TO_SEC(timediff(DATE_ADD(start, INTERVAL 1 MONTH),start)) as genau_ein_monat from zeiten

      sofern du beide ergebnisse vergleichst, weißt du, ob es 1 monat ist, weniger oder mehr .....

      PS: nur beispiele ;)

  1. hi,
    könnt Ihr mir bitte helfen.
    Habe 2 timestamps, $t_alt und $t_neu.
    wie kann ich nun feststellen, wieviel monate zwischen den beiden timestamps unterschied sind? jahresübergreifend wäre auch noch geschickt...
    Danke

    Kommt Drauf an, wie Du es definierst!
    30.3. - 30.4. 1 Monat
    31.3. - 30.4. 1 Monat ?
    28.2. - 28.3. 1 Monat
    28.2. - 29.3. 1 Monat ?
    28.2. - 29.3. 1 Monat ?
    28.2. - 30.3. 1 Monat !?

    1. die frage ist in dem fall recht einfach zu beantworten.
      es sind nur daten vom jeweils 1. eines monats.
      aber nun zu prüfen, ob es ein vielfaches von 31 o.ä. ist, wäre doch etwas unsauber... gibts nichts geeigneteres?
      danke für weitere infos

  2. hi Tanja,

    Habe 2 timestamps, $t_alt und $t_neu.
    wie kann ich nun feststellen, wieviel monate zwischen den beiden timestamps unterschied sind? jahresübergreifend wäre auch noch geschickt...

    Wenn die Zahl korrekt berechnet werden soll, kommen Schätzformeln, wie das Teilen der Tagesdifferenz durch 30 wohl nicht in Frage. Daher hätte ich (für eine reine PHP-Lösung des Problems) folgende Funktion anzubieten:

      
    function foxy_month_diff(  
      $ts_alt,  
      $ts_neu  
    ) {  
      if($ts_alt > $ts_neu ) return(FALSE);  
      
      $alt = getdate($ts_alt);  
      $neu = getdate($ts_neu);  
      
      list($years, $months, $days) = foxy_date_diff(  
        $alt['year'], $alt['mon'], $alt['mday'],  
        $neu['year'], $neu['mon'], $neu['mday']  
      );  
      
      return($years * 12 + $months);  
    }  
    
    

    Sie basiert auf einigen anderen Kalenderfunktionern, die ich mir vor längerer Zeit gebastelt hatte, um Abstände zwischen zwei Daten in Jahren, Monaten und Tagen zu berechnen. Der Quellcode mag etwas umständlich erscheinen, aber er diente vor allem zur Demonstration von Kalenderberechnungen (und deren Komplexität). Alle Funktionen liefern FALSE zurück, wenn ungültige Werte übergeben werden.

      
    function foxy_date_diff(  
      $year1 = FALSE,  // Datum alt  
      $month1 = FALSE, // dieses Datum muss kleiner oder  
      $day1 = FALSE,   // gleich dem "neuen" Datum sein  
      
      $year2 = FALSE,  // Datum neu  
      $month2 = FALSE,  
      $day2 = FALSE  
    ) {  
      // sanity checks  
      if(!is_integer($month1) || $month1 < 1 || $month1 > 12) return(FALSE);  
      if(!is_integer($month2) || $month2 < 1 || $month2 > 12) return(FALSE);  
      
      // das brauchen wir später noch  
      $days_in_month1 = foxy_days_in_month($year1, $month1);  
      
      if(!is_integer($day1) || $day1 < 1 || $day1 > $days_in_month1) return(FALSE);  
      if(!is_integer($day2) || $day2 < 1 || $day2 > foxy_days_in_month($year2, $month2) ) return(FALSE);  
      
      $diff_years = FALSE;  
      $diff_months = FALSE;  
      $diff_days = FALSE;  
      
      // Tageswerte ermitteln  
      $days_in_month1 = foxy_days_in_month($year1, $month1);  
      
      if($year1 < $year2) $diff_years = $year2 - $year1 - 1;  
      // gleiches Jahr  
      elseif($year1 == $year2) {  
        $diff_years = 0;  
        if($month1 < $month2) $diff_months = $month2 - $month1 - 1;  
        // gleicher Monat  
        elseif($month1 == $month2) {  
          $diff_months = 0;  
          if($day1 < $day2)$diff_days = $day2 - $day1;  
          elseif($day1 == $day2)$diff_days = 0;  
          else return(FALSE);  
        }  
        else return(FALSE);  
      }  
      else return(FALSE);  
      
      if(FALSE === $diff_days) $diff_days = $day2 + $days_in_month1 - $day1;  
      if(FALSE === $diff_months) $diff_months = $month2 + 12 - $month1 - 1;  
      
      if($diff_days > $days_in_month1) {  
        $diff_days = $diff_days - $days_in_month1;  
        $diff_months++;  
      }  
      
      if($diff_months > 12) {  
        $diff_months = $diff_months - 12;  
        $diff_years++;  
      }  
      
      return( array($diff_years, $diff_months, $diff_days));  
    }  
      
    function foxy_days_in_month(  
      $year = FALSE,  
      $month = FALSE  
    ) {  
      // ein 30-Tage-Monat?  
      if(  
        $month == 4 or  
        $month == 6 or  
        $month == 9 or  
        $month == 11  
      ) {  
        return 30;  
      }  
      // Februar-Tage berechnen  
      elseif($month == 2) {  
        if( foxy_is_leap_year($year) ) return(29);  
        else return(28);  
      }  
      // im Oktober 1582 wurden die Tage 5 bis 14 gestrichen  
      elseif( ($year == 1582) and ($month == 10) ) {  
       return 21;  
      }  
      // einer der anderen Monate  
      return 31;  
    }  
      
    function foxy_is_leap_year(  
      $year = FALSE  
    ) {  
      if(FALSE === $year) return(FALSE);  
      if( $year % 4 != 0 ) return(FALSE);    // alle nicht durch 4 teilbaren Jahre (die meisten);  
      // 1600 war das erste Jahrhundert, dass nach der neuen Regel ein Schaltjahr war  
      if($year >= 1600 && ($year % 400 == 0) ) return(TRUE); // alle Jahrhunderte, die durch 4 teilbar sind  
      if( $year % 100 == 0 ) return(FALSE);  // alle anderen Jahrhunderte  
      return(TRUE);                          // alle anderen durch 4 teilbaren Jahre  
    }  
    
    

    Angewendet (oder angewandt) sieht das viel einfacher aus.
    Folgendes Stück PHP-Code gibt die Zahl der vergangenen Monate
    seit der Eröffnung des SELFHTML-Forums aus:

      
    // Test des Ganzen:  
    $ts_alt = mktime(0, 0, 0, 7, 26, 1998);  
    $ts_neu = time(); // jetzt  
      
    $diff = foxy_month_diff($ts_alt, $ts_neu);  
    if(FALSE === $diff) exit('Fehlerhafte Datumsangabe!');  
    printf('Anzahl der Monate: %s', $diff );  
    exit();
    

    MffG
    EisFuX

    1. wow! danke, werds mal durchstöbern und testen.

    2. hallo,
      kurz getestet und nen bug gefunden... :(
      $ts_alt = mktime(0, 0, 0, 8, 1, 2006);
      $ts_neu = mktime(0, 0, 0, 7, 1, 2006);
      => returns false :(
      warum?
      danke

      1. Hallo Tanja,

        hallo,
        kurz getestet und nen bug gefunden... :(

        Kein Bug -- ein Feature! ;-)

        $ts_alt = mktime(0, 0, 0, 8, 1, 2006);
        $ts_neu = mktime(0, 0, 0, 7, 1, 2006);
        => returns false :(

        warum?

        Das "neue" Datum sollte "größer" sein als das "alte" (oder gleich).
        Sonst macht das ja keinen Sinn. Das steht auch als Kommentar hinter
        den Parametern von foxy_date_diff().

        Ich sehe das ganze auch eher als Codebeispiel und Grundlage für eine einfachere
        Funktion zur Berechnung des Monatsabstandes. Denn das ganze Zeug mit den Tagen
        die ein Monat hat, ist nur dann nötig, wenn man auch die Tageszahl mit berechnen
        will.

        MffG
        EisFuX

        1. echo $begrüßung;

          Das "neue" Datum sollte "größer" sein als das "alte" (oder gleich).
          Sonst macht das ja keinen Sinn.

          Ach was. Man kann von einem bestimmten Zeitpunkt aus ebenso gut in die Vergangenheit als auch in die Zukunft schauen und dabei irgendwelche Berechnungen angestellt haben wollen. Wenn du diese Größer/Kleiner-Prüfung machst kannst auch auch gleich die Werte in eine dir genehme Reihenfolge bringen.

          echo "$verabschiedung $name";

          1. printf('Hallo %s!', $name_vorposter);

            Das "neue" Datum sollte "größer" sein als das "alte" (oder gleich).
            Sonst macht das ja keinen Sinn.

            Ach was. Man kann von einem bestimmten Zeitpunkt aus ebenso gut in die Vergangenheit als auch in die Zukunft schauen und dabei irgendwelche Berechnungen angestellt haben wollen. Wenn du diese Größer/Kleiner-Prüfung machst kannst auch auch gleich die Werte in eine dir genehme Reihenfolge bringen.

            Den Gedanken hatte ich auch schon. Aber die Funktion date_diff() hatte ich ursprünglich gebastelt, weil in irgendeinem Web-Board jemand wissen wollte, wie man das Alter in Jahren, Monaten und Tagen ausrechnen kann. Also den Zeitabstand von der Geburt eines Menschen bis zum heutigen Tag. Deswegen die Einschränkung. Mir ist nämlich bisher noch niemand untergekommen, der ein negatives Alter aufzuweisen hatte ... ;-)

            Nebenbei wäre die Prüfung und der Tausch der beiden Daten aufwändiger als meine bei passender Gelegenheit eingestreuten return(FALSE)-Anweisungen ...

            Und letztendlich war es nur als Anregung gedacht, zum SELBST-Bauen einer Funktion, die das nur mit Monaten macht ...

            printf('MffG %s', $mein_name);

            1. Hallo EisFuX,

              Das "neue" Datum sollte "größer" sein als das "alte" (oder gleich).
              Sonst macht das ja keinen Sinn.

              Ach was. Man kann von einem bestimmten Zeitpunkt aus ebenso gut in die Vergangenheit als auch in die Zukunft schauen und dabei irgendwelche Berechnungen angestellt haben wollen. Wenn du diese Größer/Kleiner-Prüfung machst kannst auch auch gleich die Werte in eine dir genehme Reihenfolge bringen.

              Den Gedanken hatte ich auch schon. Aber ...
              Nebenbei wäre die Prüfung und der Tausch der beiden Daten aufwändiger als meine bei passender Gelegenheit eingestreuten return(FALSE)-Anweisungen ...

              Naja, man kann ja bei den Timestamps ansetzen, da ist der Vergleich noch einfach:

                
              function foxy_month_diff(  
                $ts_alt,  
                $ts_neu  
              ) {  
                // "Vertauschen", falls alt größer als neu ...  
                if($ts_alt > $ts_neu ) {  
                  $alt = getdate($ts_neu);  
                  $neu = getdate($ts_alt);  
                }  
                else {  
                  $alt = getdate($ts_alt);  
                  $neu = getdate($ts_neu);  
                }  
                
                list($years, $months, $days) = foxy_date_diff(  
                  $alt['year'], $alt['mon'], $alt['mday'],  
                  $neu['year'], $neu['mon'], $neu['mday']  
                );  
                
                return($years * 12 + $months);  
              }
              

              MffG
              EisFuX

  3. hi,

    noch was aus meiner anfängerzeit; folglich nicht sehr schön... aber es funktioniert:
    <?
    function difference_in_months($ts1,$ts2)
    {
     if((!empty($ts1))AND(!empty($ts2)))
     {
      $y1=date('Y',$ts1);
      $y2=date('Y',$ts2);
      $m1=date('n',$ts1);
      $m2=date('n',$ts2);
      $d1=$y1*12+$m1;
      $d2=$y2*12+$m2;
      $d=$d2-$d1;
      return $d;
     }
     else
     {
      return false;
     }
    }
    ?>