bense: Mitternachtstimestamp herausfinden

Hallo zusammen!

Ich habe einen PHP-Timestamp, mit irgendeiner Zeit des Tages. Nun möchte ich den "Nullpunkt" des Tages herausfinden. Also quasi Mitternacht, 0:00 des entsprechenden Tages. Wie mache ich jetzt das, damit es am wenigsten Rechenpower benötigt? Ich muss diese Abfrage eben ein paar tausend Mal machen, darum meine Sorge um die Performance.

Dass es mit mktime(0,0,0,date("m",$timestamp),date("d",$timestamp),date("Y",$timestamp)) funktioniert, weiss ich. Aber ist das effizient? Oder sollte ich den Timestamp lieber mit Rechnen umwandeln? Z.B. durch 24*3600 teilen, Kommastellen abschneiden und wieder mal 24*3600 rechnen?

Danke und Gruss

  1. Hallo,

    sowohl in der Prozessorlast, als auch in der Geschwindigkeit ist

    $d=$timestamp/86400;
       $d=((int) $d)*86400;

    vorzuziehen. In meiner kleinen Testreihe habe ich 1.000.000 mal oberes gegen

    $d=mktime(0,0,0,date("m",$timestamp),date("d",$timestamp),date("Y",$timestamp));

    in einer Schleife antreten lassen. Es entsprecht einem Verhältnis von ca 1/7 !

    Gruß aus Berlin!
    eddi

    --
    at, wie er leibt und lebt auf ein Posting
    > > Nein, ich denke nicht.
    gepromptet
    > Das empfiehlt sich aber.
    :))))
    1. Moin!

      sowohl in der Prozessorlast, als auch in der Geschwindigkeit ist

      $d=$timestamp/86400;
         $d=((int) $d)*86400;
      vorzuziehen. In meiner kleinen Testreihe habe ich 1.000.000 mal oberes gegen
         $d=mktime(0,0,0,date("m",$timestamp),date("d",$timestamp),date("Y",$timestamp));

      dann müsste aber doch:

      $d = int($timestamp/86400)*86400;

      noch schneller sein?

      MFFG (Mit freundlich- friedfertigem Grinsen)

      fastix®

      --
      Als Freiberufler bin ich immer auf der Suche nach Aufträgen: Schulungen, Development. Auch  für seriöse Agenturen.
      1. Moin Moin!

        dann müsste aber doch: $d = int($timestamp/86400)*86400; noch schneller sein?

        Das riecht ja fast nach Initiativstrafe ;)

        Gruß aus Berlin!
        eddi

        --
        at, wie er leibt und lebt auf ein Posting
        > > Nein, ich denke nicht.
        gepromptet
        > Das empfiehlt sich aber.
        :))))
        1. Hello,

          um welchen Wertebereich bei den Eingangswerten handelt es ich denn?
          Um ein Jahr oder um mehr?
          Man könnte das nämlich auch ein einziges Mal berechnen lassen und abspeichern. Es gibt 365/366 Tage im Jahr, und jeder hat einen "Start-Stamp" für 00:00:00. Der verschiebt sich bei uns auch nur an zwei Tagen im Jahr um 3600 (Sommerzeitumstellung)

          Harzliche Grüße aus http://www.annerschbarrich.de

          Tom

          --
          Fortschritt entsteht nur durch die Auseinandersetzung der Kreativen
          Nur selber lernen macht schlau
          1. Hallo...

            Ja, das ganz soll ja das nächste Jahr auch noch funktionieren und so müsste ich ja jedes Jahr wieder alle Tage durchrechnen, da sich ja der Timesstamp z.B. für den 3. Juli jedes Jahr ändert.

            Daher glaube ich, dass die vorhergenannte Methode effizienter ist.

            Nebenbei: Die Lösung von fastix hat noch Syntaxfehler drin, es müsste wohl eher $d = ((int) ($timestamp/86400))*86400 heissen, oder? Ausserdem muss ich bei unserer Zeitzone noch 7200 abzählen, damit ich genau auf 0:00 Uhr komme. Oder mache ich da einen Überlegungsfehler?

            Danke und Gruss

            1. Hello,

              Ja, das ganz soll ja das nächste Jahr auch noch funktionieren und so müsste ich ja jedes Jahr wieder alle Tage durchrechnen, da sich ja der Timesstamp z.B. für den 3. Juli jedes Jahr ändert.

              Daher glaube ich, dass die vorhergenannte Methode effizienter ist.

              Nein, das ist in diesem Fall die schlechtere Methode.

              Hinterleg eine Datei, in der für alle Tage des Jahres die Referenz gespeichert wird. Die kann man mit einem bedingten include dann dazuladen, wenn da, oder eben erzeugen, wenn ein Tag aus einem noch nicht berechneten Zeitraum kommt. Das lohnt sich natürlich nur dann, wenn die Argumentemenge (zumindest eine zeitland) immer nur in denselben engen Bereich fällt.

              Harzliche Grüße aus http://www.annerschbarrich.de

              Tom

              --
              Fortschritt entsteht nur durch die Auseinandersetzung der Kreativen
              Nur selber lernen macht schlau
              1. Moin Tom :)

                Hinterleg eine Datei, in der für alle Tage des Jahres die Referenz gespeichert wird. Die kann man mit einem bedingten include dann dazuladen, wenn da, oder eben erzeugen, wenn ein Tag aus einem noch nicht berechneten Zeitraum kommt. Das lohnt sich natürlich nur dann, wenn die Argumentemenge (zumindest eine zeitland) immer nur in denselben engen Bereich fällt.

                Der include-Zugriff auf eine Datei mit 164 Byte verzögert das Script um den Faktor 35! Ich kann in dem Falle nur anraten $d=(int)($timestamp/86400)*86400; zu verwenden, was seinerseits ca 20% schneller ist, als mein erster Vorschlag.
                (Hat mich grade selbst schockiert, da ich sehr gerne mit include() Scriptschnipsel wiederverwende/auslagere)

                Gruß aus Berlin!
                eddi

            2. Hallo

              Nebenbei: Die Lösung von fastix hat noch Syntaxfehler drin, es müsste wohl eher $d = ((int) ($timestamp/86400))*86400 heissen, oder?

              Nö, fastix' Lösung ist syntaxmäßig richtig: $d = int($timestamp/86400)*86400;

              Zuerst wird mit int($timestamp/86400) der Timestamp durch die Anzahl der
              Sekunden des Tages geteilt und das Ganze dann mit int() in eine Ganzzahl
              verwandelt. Das ist also schon geklammert.
              Erst das daraus resultierende Ergebnis wird wieder mit der Zahl der Sekunden
              des Tages multipliziert.

              Ausserdem muss ich bei unserer Zeitzone noch 7200 abzählen, damit ich genau auf 0:00 Uhr komme. Oder mache ich da einen Überlegungsfehler?

              Das kommt auf die Zeitzoneneinstellung des Servers, auf dem das Skript läuft, an.
              Außerdem: unsere Zeitzone (MEZ) liegt nur eine Stunde von der GMT entfernt.

              Tschö, Auge

              --
              Die Musik drückt aus, was nicht gesagt werden kann und worüber es unmöglich ist zu schweigen.
              (Victor Hugo)
              1. Hallo,

                Nebenbei: Die Lösung von fastix hat noch Syntaxfehler drin, es müsste wohl eher $d = ((int) ($timestamp/86400))*86400 heissen, oder?

                Nö, fastix' Lösung ist syntaxmäßig richtig: $d = int($timestamp/86400)*86400;

                Fatal error: Call to undefined function: int()

                Gruß aus Berlin!
                eddi

                1. Moin!

                  Hallo,

                  Nebenbei: Die Lösung von fastix hat noch Syntaxfehler drin, es müsste wohl eher $d = ((int) ($timestamp/86400))*86400 heissen, oder?

                  Nö, fastix' Lösung ist syntaxmäßig richtig: $d = int($timestamp/86400)*86400;

                  Fatal error: Call to undefined function: int()

                  Mein Gott! Dann nimm:

                  $d=floor($timestamp/86400)*86400;
                  http://de2.php.net/manual/de/function.floor.php

                  MFFG (Mit freundlich- friedfertigem Grinsen)

                  fastix®

                  --
                  Als Freiberufler bin ich immer auf der Suche nach Aufträgen: Schulungen, Development. Auch  für seriöse Agenturen.
                  1. Moin Moin!

                    Mein Gott!

                    ?

                    $d=floor($timestamp/86400)*86400;

                    echo microtime().'<br>';
                    for($i=0;$i<10000000;$i++)
                     $d=floor(time()/86400)*86400;
                    echo microtime().'<br>';
                    for($i=0;$i<10000000;$i++)
                     $d=((int)(time()/86400))*86400;
                    echo microtime();

                    Dabei ist Dein erster Ansatz mit (int) immernoch der beste und hängt floor() um rund 20% ab.

                    Gruß aus Berlin!
                    eddi

                    1. Moin! Das geht noch besser .)

                      <?
                      $d1=0;
                      $d2=0;
                      $d3=0;
                      $d=time();

                      $start= microtime();
                      for($i=0;$i<1000;$i++)   $d1=floor($d/86400)*86400;
                      echo "floor:".(microtime()-$start)." - ".$d1."\n";

                      $start= microtime();
                      for($i=0;$i<1000;$i++)   $d2=((int)($d/86400))*86400;
                      echo "int  :".(microtime()-$start)." - ".$d2."\n";

                      $start= microtime();
                      for($i=0;$i<1000;$i++)   $d3=bcmul(bcdiv($d, 86400, 0), 86400, 0);
                      echo "bc   :".(microtime()-$start)." - ".$d3."\n";
                      ?>

                      floor:0.002028 - 1095984000
                      int  :0.001501 - 1095984000
                      bc   :0.010372 - 1095984000

                      :)

                      MFFG (Mit freundlich- friedfertigem Grinsen)

                      fastix®

                      --
                      Als Freiberufler bin ich immer auf der Suche nach Aufträgen: Schulungen, Development. Auch  für seriöse Agenturen.
                      1. Re:

                        irgentwie hat meine Mühle Probleme mit der Subtraktion von microtime() - $start :(  (die Zahlen sehen von Test zu Test etwas wirr aus)
                        Also noch ein wenig rumprobiert, aber die Zahlen weisen in die selbe Richtung:

                        <?php
                        ini_set('max_execution_time',200);
                        $d1=0;
                        $d2=0;
                        $d3=0;
                        $d=time();
                        $u=10000000;

                        touch('auswertung.txt');
                        $dat=fopen('auswertung.txt','a');

                        $start=explode(' ',microtime());
                        $start=$start[1].substr($start[0],-9);

                        for($i=0;$i<$u;$i++)
                           $d1=floor($d/86400)*86400;

                        $end=explode(' ',microtime());
                        $end=$end[1].substr($end[0],-9);
                        fputs($dat,"floor:".str_pad(($end-$start),16)." - ".$d1."\n");

                        $start=explode(' ',microtime());
                        $start=$start[1].substr($start[0],-9);

                        for($i=0;$i<$u;$i++)
                           $d2=((int)($d/86400))*86400;

                        $end=explode(' ',microtime());
                        $end=$end[1].substr($end[0],-9);
                        fputs($dat,"int  :".str_pad(($end-$start),16)." - ".$d2."\n");

                        $start=explode(' ',microtime());
                        $start=$start[1].substr($start[0],-9);

                        for($i=0;$i<$u;$i++)
                           $d3=bcmul(bcdiv($d, 86400, 0), 86400, 0);

                        $end=explode(' ',microtime());
                        $end=$end[1].substr($end[0],-9);
                        fputs($dat,"bc   :".str_pad(($end-$start),16)." - ".$d3."\n");
                        fclose($dat);
                        ?>

                        floor:26.531457901     - 1095984000
                        int  :20.1989428997    - 1095984000
                        bc   :119.399335146    - 1095984000

                        JUHU - endlich hab' ich mal ein vernünftiges Testscript! Danke Dir :)

                        Gruß aus Berlin!
                        eddi

                        1. Moin,

                          $d2=((int)($d/86400))*86400;

                          So, und das jetzt noch ohne überflüssige Division/Multiplikation:

                          $d3=$d - $d % 86400;

                          floor:36.299628973     - 1095984000
                          int  :30.1205070019    - 1095984000
                          mod  :29.3255560398    - 1095984000

                          --
                          Henryk Plötz
                          Grüße von der Ostsee
                          ~~~~~~~~ Un-CDs, nein danke! http://www.heise.de/ct/cd-register/ ~~~~~~~~
                          ~~ Help Microsoft fight software piracy: Give Linux to a friend today! ~~
                          1. Hello,

                            So, und das jetzt noch ohne überflüssige Division/Multiplikation:

                            $d3=$d - $d % 86400;

                            floor:36.299628973     - 1095984000
                            int  :30.1205070019    - 1095984000
                            mod  :29.3255560398    - 1095984000

                            Irgendwie sollten wir diese ganzen Performance-Übungen mal sammeln und auswerten. Hier sind ja schön öfter gute Tipps durchgelaufen. Auch manchmal, ohne dass sie wahrgenommen werden. Aber die Sachen sind Gold wert.

                            Gibt denn das Forum im inneren berich eine Klassifikation der Threads her? Da reicht ja eine "Ankreuzliste", in der mehrere Optionen markiert werden können.

                            Harzliche Grüße aus http://www.annerschbarrich.de

                            Tom

                            --
                            Fortschritt entsteht nur durch die Auseinandersetzung der Kreativen
                            Nur selber lernen macht schlau