Berechnen Sie die Gesamtsekunde in PHP DateInterval

98

Wie lässt sich die Gesamtzahl der Sekunden zwischen zwei Daten am besten berechnen? Bisher habe ich etwas in der Art versucht:

$delta   = $date->diff(new DateTime('now'));
$seconds = $delta->days * 60 * 60 * 24;

Die daysEigenschaft des DateInterval-Objekts scheint jedoch im aktuellen PHP5.3-Build fehlerhaft zu sein (zumindest unter Windows wird immer der gleiche 6015Wert zurückgegeben). Ich habe auch versucht, dies auf eine Weise zu tun, bei der die Anzahl der Tage in jedem Monat (Runden auf 30), die Schaltjahre usw. nicht erhalten bleiben:

$seconds = ($delta->s)
         + ($delta->i * 60)
         + ($delta->h * 60 * 60)
         + ($delta->d * 60 * 60 * 24)
         + ($delta->m * 60 * 60 * 24 * 30)
         + ($delta->y * 60 * 60 * 24 * 365);

Aber ich bin wirklich nicht glücklich mit dieser halbherzigen Lösung.

efritz
quelle
Was ist das Ergebnis von $delta->format("%r%s")?
Warren
1
@ Warrenm Das Problem mit formatist, wenn sagen, die Anzahl der Sekunden ist 0, während die Anzahl der Minuten 1 ist, $delta->format("%r%s")stellt sich heraus, 0 zu sein :(
Vadim Samokhin
4
Schlimmer noch, wenn jemand spricht, der jetzt einen Fehler behebt, der bei der Codeüberprüfung durch einen Codierer behoben wurde, der Ihren EXAKTEN Code oben eingefügt hat - nicht jeder Monat hat 30 Tage und nicht jedes Jahr hat 365 Tage. :) [Edit: und dieser Codierer könnte ich selbst gewesen sein!]
Taiganaut

Antworten:

204

Könnten Sie nicht stattdessen die Zeitstempel vergleichen ?

$now = new DateTime('now');
$diff = $date->getTimestamp() - $now->getTimestamp()
Ben
quelle
11
Ich glaube, ich habe nicht RTFM ... Das ist, wonach ich gesucht habe; Vielen Dank!
Efritz
3
+1: schön und sauber! Beachten Sie, dass die getTimestamp()Methode in PHP> = 5.3.0 verfügbar ist.
Sk8erPeter
6
Wenn Sie mit PHP 5.2 auf Ihrem beschissenen Shared Hoster nicht weiterkommen, verwenden Sie format('U')stattdessen getTimestamp().
Chiborg
4
Ihre Lösung ist nicht kompatibel mit Jahr 2038 Fehler
Jack M.
9
@ JackM. Gut zu wissen. Ich hoffe, dass alles, was gerade gebaut wird, im Jahr 2037 nicht mehr läuft. Sie können gerne eine fehlerfreie alternative Lösung für das Jahr 2038 anbieten.
Ben
34

Mit dieser Funktion können Sie die Gesamtdauer eines DateInterval-Objekts in Sekunden abrufen

/**
 * @param DateInterval $dateInterval
 * @return int seconds
 */
function dateIntervalToSeconds($dateInterval)
{
    $reference = new DateTimeImmutable;
    $endTime = $reference->add($dateInterval);

    return $endTime->getTimestamp() - $reference->getTimestamp();
}
dave1010
quelle
2
Es ist zu beachten, dass DateTimeImmutable nur ab PHP 5.5 oder höher verfügbar ist.
hschmieder
Ich denke, Sie müssen die Rückgabevariablen $endTimeund $referenceuntereinander ersetzen , da dies ein Minus-Ergebnis mit einem zukünftigen Intervall-Datum / Uhrzeit-Wert ergibt.
AlexioVay
Ich glaube auch nicht, dass der Zeitstempel in Sekunden angegeben ist. PHP DateTime = Horrific API
Quadrivium
5

Sie könnten es so machen:

$currentTime = time();
$timeInPast = strtotime("2009-01-01 00:00:00");

$differenceInSeconds = $currentTime - $timeInPast;

time () gibt die aktuelle Zeit in Sekunden seit der Epochenzeit (1970-01-01T00: 00: 00) zurück, und strtotime macht dasselbe, jedoch basierend auf einem bestimmten Datum / einer bestimmten Uhrzeit, die Sie angeben.

xil3
quelle
4
static function getIntervalUnits($interval, $unit)
{
    // Day
    $total = $interval->format('%a');
    if ($unit == TimeZoneCalc::Days)
        return $total;
    //hour
    $total = ($total * 24) + ($interval->h );
    if ($unit == TimeZoneCalc::Hours)
        return $total;
    //min
    $total = ($total * 60) + ($interval->i );
    if ($unit == TimeZoneCalc::Minutes)
        return $total;  
    //sec
    $total = ($total * 60) + ($interval->s );
    if ($unit == TimeZoneCalc::Seconds)
        return $total;  

    return false;
}
Hufzuz
quelle
0

Es fühlt sich immer gut an, wenn das, was Sie brauchen, bereits als Klasse vorhanden ist. In Ihrem Fall benötigen Sie insgesamt Sekunden. Warum nicht eine Klasse daraus machen? Der Code könnte so aussehen:

(new TotalFullSeconds(
    new IntervalFromRange(
        new DateTimeFromISO8601String('2017-07-03T14:27:39+00:00'),
        new DateTimeFromISO8601String('2017-07-05T14:27:39+00:00')
    )
))
    ->value()

Sie sind nicht nur intuitiv, sondern können auch von der automatischen Vervollständigung Ihrer IDE profitieren.

Weitere nützliche Implementierungen finden Sie in dieser Bibliothek .

Vadim Samokhin
quelle
-8

Sie können einfach die harten Zahlen eingeben (anstelle von 60 * 60 - 3600 eingeben), damit sie nicht jedes Mal berechnet werden müssen.

Bearbeiten - Die Nummer wurde basierend auf Ihrem Kommentar korrigiert.

Duniyadnd
quelle
Das wäre in Ordnung und würde in PHP wahrscheinlich einen Bruchteil einer Sekunde schneller laufen, aber ich habe immer noch die gleiche Fehlberechnung wie im obigen Beispiel.
Efritz