Justin: Zeitabstand richtig ermitteln

Huhu liebes Forum, ich habe ein kleines Problem:

Ich nutze Timestamps um einen Punkt zu speichern, an dem eine Datei auf eine bestimmte Art bearbeitet wurde - bzw. eine bestimmte Funktion ausgeführt wurde.
Es gibt immmer nur einen dieser Timestamps, der aktuell ist.
Da es erforderlich ist, zu wissen, wieviel Zeit seit diesem Zeitpunkt vergangen ist (Sekunden, Minuten, Stunden, Tage, Monate und Jahre), habe ich folgendes gemacht:

Nennen wir den aktuellen Timestamp mal "starttime"...

date("s", (time() - $starttime)) //für Sekunden. Dasselbe mit "i", "H", "d", "m" und "Y"

Angezeigt wird auch alles richtig, nur mit dem Problem, dass alle Werte (sofern nicht wirklich "01") 01 anzeigen.

Um das zu veranschaulichen:
Angenommen, ich habe vor genau 1 Monat, 6 Tagen, 9 Stunden, 1 Minute und 37 Sekunden die besagte Funktion aufgerufen, würde nun als Ausgabe in der Datei stehen "01 Jahren, 01 Monaten, 6 Tagen, 9 Stunden, 01 Minuten und 37 Sekunden" - was natürlich total falsche Informationen ausgibt...

Ich kann mir gut denken, dass ich ein falsches Format für meinen Zeitpunkt gewählt habe, oder einfach falsch abfrage... aber so möchte ich dies nicht weiter nutzen müssen.

Hat jemand bitte einen Tipp für mich, wie ich weiter arbeiten kann?
Liebe Grüße, Justin

  1. Angezeigt wird auch alles richtig, nur mit dem Problem, dass alle Werte (sofern nicht wirklich "01") 01 anzeigen.

    Entschuldigung, habe mich falsch ausgedrückt:
    Wenn der Wert nicht vorhanden ist (quasi 0 wäre (im Beispiel wären es die Jahre)), dann zeigt er "01" an.
    Ist der Wert "01", zeigt er auch "01" an.

    Ich hoffe ihr könnt mir helfen.

    Funktionen, die das letzte Speichern der Datei, ändern der Datei oder einen Scriptaufruf speichern brauche ich nicht.
    Vorallem, weil ich die Zeit ja anzeigen will (in dem Format, wie es im Beispiel steht), ohne, dass der User dann erstmal einen Kalender suchen muss.

    Er soll wissen, dass die Funktion in der Datei (ist aber nur eine von vielen) Datei z.B. 3 Monate, 17 Tage und 5 Stunden nicht mehr aufgerufen wurde, um daraus weitere Handlungen ziehen zu können.

    Bitte helft mir, ich verzweifel total =(
    LG Justin

    1. Hello,

      Bitte helft mir, ich verzweifel total =(

      ich habe die Funktion selbst noch nie im Detail betrachtet, könnte mir aber vorstellen, dass das etwas mit den Wertebereichen der einzelnen Bestandteile zu tun hat.
      Hilft dir bei deinem Problem vielleicht der Kommentar bzw. die Funktion von "steve at NOSPAMPLEASE dot peartenterprises dot com" im PHP-Manual weiter?

      MfG
      Rouven

      --
      -------------------
      sh:| fo:} ch:? rl:( br:& n4:{ ie:| mo:} va:) js:| de:] zu:| fl:( ss:) ls:& (SelfCode)
      Eine Bilanz ist wie der Bikini einer Frau. Sie zeigt fast alles, aber verdeckt das Wesentliche  --  Günter Stotz, Regierungsdirektor des baden-württembergischen Wirtschaftsministeriums
      1. Hello,

        » Bitte helft mir, ich verzweifel total =(
        ich habe die Funktion selbst noch nie im Detail betrachtet, könnte mir aber vorstellen, dass das etwas mit den Wertebereichen der einzelnen Bestandteile zu tun hat.

        Das ist richtig, date() interprettiert nicht mögliche Werte so, dass sie möglich werden. date() gibt eben Zeitpunkte wieder und keinen Zeitraum. Du möchtest aber einen Zeitraum.
        Ggf. könntest du das mit / und % lösen, aber ich befürchte dass da Ungenauigkeiten hinein kommen (Schaltjahre und so weiter). Also wirst du wahrscheinlich eine länge Bedinungs-Kette schreiben müssen, die die Jahrenzahlen einzeln ermittelt, von einander subtrahiert und bei den Monaten dann guckt ob die Monate in unterschiedlichen Jahren liegen oder ob man die auch einfach subtrahieren kann (nicht dass auf bei Februar minus Oktober -8 erhältst) und so fort. Ja, sind viel mehr Code-Zeilen, erscheint mir aber die einzige Möglichkeit dein Ziel zu erreichen.

        Allerdings klingt deine anfängliche Beschreibung so, als bräuchtest du diese ganzen Werte nicht. Wenn es nur um die Identifikation eines Zeitpunkts geht, dass ist der Timestamp ansich (also die Zeit oder Differenz in Sekunden) doch ausreichend.

        --
        sh:( fo:| ch:? rl:( br:& n4:& ie:{ mo:} va:) de:µ_de:] zu:) fl:( ss:| ls:[ js:(
        1. echo $begrüßung;

          Das ist richtig, date() interprettiert nicht mögliche Werte so, dass sie möglich werden.

          Für date() gibt es keine nicht möglichen Werte. date() nimmt einen Unix-Timestamp entgegen, der einen auf die Sekunde genauen Zeitpunkt (Schaltsekunden werden nicht gezählt) als Distanz zum 1.1.1970 0 Uhr UTC angibt. Ungültige Zeiten (z.B. 25 Uhr, 30. Februar) lassen sich mit einem Unix-Timestamp nicht darstellen, also kann date() auch keine unmöglichen Werte daraus interpretieren.

          date() gibt eben Zeitpunkte wieder und keinen Zeitraum.

          Oder genauer gesagt: date() interpretiert das Argument als Zeitpunkt.

          Ggf. könntest du das mit / und % lösen, aber ich befürchte dass da Ungenauigkeiten hinein kommen (Schaltjahre und so weiter).

          Wenn man zwei Unix-Timestamps hat, und die Differenz daraus ermittelt, bekommt man die Anzahl der Sekunden. Diese ist immer unabhängig von Schaltjahren oder Sommerzeiten. Man kann im Prinzip nur diese Sekundenanzahl in Stunden, Minuten und (restlichen) Sekunden aufteilen. Unter der Annahme, ein Tag habe 24 Stunden, kann man auch noch Tage ausrechnen. Aber Monate sind für eine Differenz nicht mehr sinnvoll ermittelbar. Es sei denn, man legt fest, ein Monat habe 30 Tage. Analoges gilt für Jahre.

          Aber je größer eine Differenz ist, destoweniger interessieren im Allgemeinen diese durch die Sonderfälle bedingten Abweichungen.

          Allerdings klingt deine anfängliche Beschreibung so, als bräuchtest du diese ganzen Werte nicht. Wenn es nur um die Identifikation eines Zeitpunkts geht, dass ist der Timestamp ansich (also die Zeit oder Differenz in Sekunden) doch ausreichend.

          Im PHP-Handbuch findet sich eine Klasse namens DateInterval. Allerdings gibt es die erst mit PHP 5.3 und beschrieben ist sie im Manual derzeit noch nicht. DateInterval::format() klingt zumindest vom Namen her, als ob es der OP brauchen könnte.

          echo "$verabschiedung $name";

  2. Hallo,

    Ich nutze Timestamps um einen Punkt zu speichern, an dem eine Datei auf eine bestimmte Art bearbeitet wurde - bzw. eine bestimmte Funktion ausgeführt wurde.

    das ist gut.

    Da es erforderlich ist, zu wissen, wieviel Zeit seit diesem Zeitpunkt vergangen ist ...

    Für wen ist das erforderlich? Für irgendein Stück Programm? Dann genügt es doch, einfach die Differenz der beiden Timestamps in Sekunden zu nehmen. Das ist eine Größe, mit der man wunderbar rechnen kann, wenn das nötig sein sollte.
    Oder für den User? Da würde ich -nur aus meiner eigenen Sicht- sagen, dass ich eine Angabe wie
     "Dieser Beitrag wurde zuletzt am **.**.** um **:** Uhr geändert"
    wesentlich informativer finde als
     "Dieser Beitrag wurde zuletzt vor ** Tagen, ** Stunden und ** Minuten geändert".

    date("s", (time() - $starttime)) //für Sekunden. Dasselbe mit "i", "H", "d", "m" und "Y"

    Und das ist ein Problem. Denn date() ist nunmal dafür gedacht, einen Timestamp (also einen Zeitpunkt) in ein "lesbares" Datum umzuwandeln. Du bildest nun aber die Differenz zweier Timestamps, das ergibt einen sehr kleinen Wert, und date() interpretiert diesen kleinen Wert nun als Datum kurz nach dem 01.01.1970 (Timestamp=0).

    Angezeigt wird auch alles richtig, nur mit dem Problem, dass alle Werte (sofern nicht wirklich "01") 01 anzeigen.

    Das mit der führenden Null bekommst du leicht weg, indem du die Strings, die date() liefert, wieder in Zahlenwerte umwandelst. Dass du bei einigen Werten 1 anstatt 0 herausbekommst, liegt aber einfach daran, dass wir die Monate und Tage mit 1 beginnend zählen, die Stunden, Minuten und Sekunden dagegen ordentlich ab 0. Subtrahiere also 1 vom Monats- und Tageswert, und 1970 vom Jahr.
    Bei längeren Zeiträumen als 1 Jahr kommt eventuell noch das von Deus Figendi angesprochene Schaltjahr-Problem dazu, bei Zeiträumen von einigen Monaten könntest du immerhin schon einen Fehler von einer Stunde durch die Sommer/Winterzeitgeschichte bekommen: Vom 27.03.2009, 08:00h bis zum 31.01.2009, 08:00h sind es zweifellos 4 Tage - aber sind das auch 96 Stunden? Oder 95? Oder doch 97?

    So long,
     Martin

    --
    Bitte komme jemand mit einem *g* zum Wochenende, damit nicht über mich gelacht wird.
      (Gunnar Bittersmann)
    1. echo $begrüßung;

      bei Zeiträumen von einigen Monaten könntest du immerhin schon einen Fehler von einer Stunde durch die Sommer/Winterzeitgeschichte bekommen: Vom 27.03.2009, 08:00h bis zum 31.01.2009, 08:00h sind es zweifellos 4 Tage - aber sind das auch 96 Stunden? Oder 95? Oder doch 97?

      Das ist kein Problem. Der Timestamp selbst ist UTC und interessiert sich nicht für Sommerzeiten. Die Anzahl der vergangenen Stunden wird auch mit Sommerzeit nicht mehr oder weniger. 24 Stunden sind 24 Stunden, egal ob es gerade 1 Uhr, 2 Uhr, 3 Uhr oder 4 Uhr usw. ist oder ich munter durch die Zeitzonen reise.

      echo "$verabschiedung $name";

      1. Hallo,

        »» Vom 27.03.2009, 08:00h bis zum 31.01.2009, 08:00h sind es zweifellos 4 Tage - aber sind das auch 96 Stunden? Oder 95? Oder doch 97?
        Das ist kein Problem. Der Timestamp selbst ist UTC und interessiert sich nicht für Sommerzeiten. Die Anzahl der vergangenen Stunden wird auch mit Sommerzeit nicht mehr oder weniger.

        völlig klar - ich wollte hier nur auf die Problematik der Zeitrechnung hinweisen: Im normalen Alltag würde man das obige Intervall als exakt 4 Tage bezeichnen, und damit wahrscheinlich mit 96 Stunden beziffern. Es sei denn, man rechnet bei den Klartext-Zeitangaben schon in UTC, was aber die wenigsten tun (außer vielleicht in der Nautik, Luft- und Raumfahrt, Meteorologie, Astronomie oder im Amateurfunk).

        24 Stunden sind 24 Stunden, egal ob es gerade 1 Uhr, 2 Uhr, 3 Uhr oder 4 Uhr usw. ist oder ich munter durch die Zeitzonen reise.

        Ja, kein Zweifel. Das tut aber hier nichts zur Sache: Das Intervall, das ich (stillschweigend MEZ/MESZ voraussetzend) genannt habe, ist nämlich *nicht* genau 96 Stunden lang, obwohl man das auf den ersten Blick annehmen möchte.

        So long,
         Martin

        --
        why the heck do you jerk think, that wir ein doppelposting nicht bemerken, wenn you zwischendurch the sprache wechselst?
          (wahsaga)
        1. echo $begrüßung;

          » »» Vom 27.03.2009, 08:00h bis zum 31.01.2009, 08:00h sind es zweifellos 4 Tage - aber sind das auch 96 Stunden? Oder 95? Oder doch 97?
          » 24 Stunden sind 24 Stunden, egal ob es gerade 1 Uhr, 2 Uhr, 3 Uhr oder 4 Uhr usw. ist oder ich munter durch die Zeitzonen reise.
          Ja, kein Zweifel. Das tut aber hier nichts zur Sache: Das Intervall, das ich (stillschweigend MEZ/MESZ voraussetzend) genannt habe, ist nämlich *nicht* genau 96 Stunden lang, obwohl man das auf den ersten Blick annehmen möchte.

          Du hast zwei Zeitstempel vorliegen. Und selbst wenn sich diese in unterschiedlichen Zeitzonen befinden, ist ihr Abstand zueinander exakt berechenbar. Dein "Blick" und die darauffolgende Suggestion ist dafür uninteressant.

          echo "$verabschiedung $name";