Meowsalot: Tage berechnen

Hallo,

ich muss die Tage zwischen einen von - bis berechnen. Dieses mache ich wie folgt:


//Von = 22.06.2018
//Bis = 24.06.2018

$startDate = new DateTime($von);
$endDate = new DateTime($bis);
$diff = $startDate->diff($endDate);

echo $diff->days;

Als Ergebnis erhalte ich jetzt 2 Tage. Stimmt eigentlich auch, ich benötige allerdings die volle Anzahl sprich inkl. dem Startdatum. In diesem Fall 3 Tage. Das heißt ich muss immer +1 dazuzählen? Allerdings würde es mein Ergebnis verfälschen wenn ich vom 22.06.2018 - 22.06.2018 habe. Das wäre ein Tag.

Gibt es noch eine andere Möglichkeit?

EDIT - 10:52 Uhr: OK, ich knn wohl immer $diff->days+1 schreiben. Denn 22.06.2018 - 22.06.2018 ergibt 0 obwohl es ein Tag ist. Warum behauptet PHP es wären 0 Tage?

Bis bald!
Meowsalot (Bernd)

  1. Hallo Meowsalot,

    Warum behauptet PHP es wären 0 Tage?

    Mysterien der Mathematik. x - x = 0. Du musst nur aufpassen, dass du keine Zeitkomponente in deinen DateTime-Objekten hast, sonst kommt ggf. was falsches raus.

    Du solltest deinen Code auch noch für die Übergänge Winter⇒Sommerzeit und Sommer⇒Winterzeit testen.

    Rolf

    --
    sumpsi - posui - clusi
    1. Hallo Rolf,

      danke für deine Antwort. Ich lass es jetzt so ausgeben

      $startDate = new DateTime($von);
      $endDate = new DateTime($bis);
      $diff = $startDate->diff($endDate);
      $tage = $diff->days+1
      
      for($i=0; $i <= $tage; $i++) {
      
      <div>
        <label style="width: 18.5%;" for="datum">Datum</label>
        <input type="text" name="datum" id="datum" value="">
      </div>
      
      <div class="textfeld">
        <label style="width: 18.5%;" for="fotos">Anzahl Fotos</label>
        <input type="text" name="fotos" id=fotos" value="">
      </div>
      
      }
      

      Was ich noch nicht ganz verstehe ist, wie kann ich das jeweilige Datum ausgeben lassen? Irgendwie stehe ich gerade voll auf dem Schlauch.

      Bis bald!
      Meowsalot (Bernd)

      1. Hallo Meowsalot,

        wenn man PHP und HTML mischt, ist es oft lesbarer, nicht die {} Notation zu verwenden, sondern die „alternative Syntax“ einzusetzen. So ein unschuldiges }, das da ganz allein im Wald steht, geht gerne mal unter. Ein fettes endfor; ist da deutlich ausdrucksstärker.

        Ausgabe von DateTime als String - guck mal unter DateTime::format

        Rolf

        --
        sumpsi - posui - clusi
        1. Hallo Rolf,

          Ausgabe von DateTime als String - guck mal unter DateTime::format

          bei der Ausgabe sind wir doch noch gar nicht? Es geht doch darum dass ich innerhalb von der Schleife das Datum neu festlegen muss?

          Es fängt im ersten Durchlauf bei $von an und im zweiten +1 Tag, im zweiten Durchlauf +2 Tage usw... oder denke ich da falsch?

          Bis bald!
          Meowsalot (Bernd)

          1. Hallo,

            Was ich noch nicht ganz verstehe ist, wie kann ich das jeweilige Datum ausgeben lassen? Ausgabe von DateTime als String bei der Ausgabe sind wir doch noch gar nicht?

            Kannst du bitte mal deinen Prozess, der deine Gedanken in Fragen übersetzt, neu kalibrieren?

            Gruß
            Kalk

          2. Hallo Meowsalot,

            Was ich noch nicht ganz verstehe ist, wie kann ich das jeweilige Datum ausgeben lassen?

            Also sind wir DOCH bei der Ausgabe.

            Dass Dir das "jeweilige" Probleme bereitet, habe ich nicht verstanden. Guck mal bei DateTime::add und drehe $startDate Tag für Tag hoch.

            Rolf

            --
            sumpsi - posui - clusi
            1. Hallo Rolf,

              Also sind wir DOCH bei der Ausgabe.

              Jupp

              Dass Dir das "jeweilige" Probleme bereitet, habe ich nicht verstanden. Guck mal bei DateTime::add und drehe $startDate Tag für Tag hoch.

              Ok, hab es so umgesetzt

              $date = date_create($von);
              
               for($i=0; $i < $tage; $i++) { 
              
              	if ($i == 0) {
              		date_add($date, date_interval_create_from_date_string('0 day'));
              	} else {
              		date_add($date, date_interval_create_from_date_string('1 day'));	
              	}
              
              echo date_format($date, 'd.m.Y');
              

              Bis bald! Meowsalot (Bernd)

              1. Hallo Meowsalot,

                nimm's mir nicht übel, aber ich leide nun mal an Verbesserungsdrang.

                Dein Code hat Geruch. Das meint: da kommen spezifische Muster vor, die auf verbesserungsfähige Programmstruktur hindeuten – code smells auf gut Englisch.

                Bei dir riecht der Umstand, dass Du innerhalb der Schleife einen bestimmten Schleifendurchlauf abfragst. Sowas signalisiert: "teile mich". D.h. wenn du den ersten Durchlauf abfragst, dann führe den Code für den ersten Durchlauf VOR der Schleife aus, und beginne die Schleife eins später. Es geht analog, wenn Du den letzten Durchlauf abfragst. Du befreist den Schleifeninhalt damit von unnötiger Logik; das ist gut für das Verständnis und die Performance. Wenn diese Trennung dazu führt, dass Du viel Code kopieren musst, dann ist das ein weiterer smell: der Schleifenrumpf war dann zu groß und möchte gerne in eine oder mehrere Funktionen ausgelagert werden.

                Einen immer gleichen Wert innerhalb einer Schleife zu erzeugen ist ebenfalls ungünstig, sowas möchte gerne vorher passieren und in einer Variablen auf Abruf warten. Ein date_add mit 0 Tagen ist wirkungslos, d.h. diesen add lassen wir einfach weg.

                Die Verbesserung wäre also - Variante 1:

                $date = new DateTime($von);
                $oneDay = new DateInterval('P1D');  // oder date_interval_create_from_date_string('1 day');
                
                schreibeZeile($date);
                
                for($i=1; $i < $tage; $i++) { 
                   $date->add($oneDay);
                   schreibeZeile($date);
                }
                
                function schreibeZeile($datum) {
                   echo $datum->format('d.m.Y');
                }
                

                oder - ohne Trennung in Vor- und Hauptlauf - einfach den add ans Ende der Schleife ziehen. Da addiert man einmal zu oft den Tag. Kann man für übersichtlichen Code verschmerzen.

                $date = new DateTime($von);
                $oneDay = new DateInterval('P1D');  // oder date_interval_create_from_date_string('1 day');
                
                for($i=0; $i < $tage; $i++) { 
                   schreibeZeile($date);
                   $date->add($oneDay);
                }
                
                function schreibeZeile($datum) {
                   echo $datum->format('d.m.Y');
                }
                

                Es ist nicht immer leicht, für solche Funktionen gute Namen zu finden. Hier hilft es oft, wenn man solche Codeblöcke zu Klassen zusammen fasst oder zumindest in namespaces aufteilt. Weiß nicht ob das Dein Ding ist, nur ein Vorschlag.

                Rolf

                --
                sumpsi - posui - clusi
  2. Hi,

    
    //Von = 22.06.2018
    //Bis = 24.06.2018
    
    $startDate = new DateTime($von);
    $endDate = new DateTime($bis);
    $diff = $startDate->diff($endDate);
    
    echo $diff->days;
    

    Als Ergebnis erhalte ich jetzt 2 Tage. Stimmt eigentlich auch, ich benötige allerdings die volle Anzahl sprich inkl. dem Startdatum. In diesem Fall 3 Tage. Das heißt ich muss immer +1 dazuzählen? Allerdings würde es mein Ergebnis verfälschen wenn ich vom 22.06.2018 - 22.06.2018 habe. Das wäre ein Tag.

    Warum wäre das verfälscht?

    Bei identischem Datum für von und bis kommt bei Deinem echo 0 raus. Wenn Du da (so wie sonst auch) 1 drauf addierst, kommt 1 raus. Paßt doch zu Deinem Wunsch.

    cu,
    Andreas a/k/a MudGuard