Wie berechnet man die Differenz zwischen zwei Daten mit PHP?

722

Ich habe zwei Daten des Formulars:

Start Date: 2007-03-24 
End Date: 2009-06-26

Jetzt muss ich den Unterschied zwischen diesen beiden in der folgenden Form finden:

2 years, 3 months and 2 days

Wie kann ich das in PHP machen?

Taryn
quelle
1
2 Jahre 94 Tage. Die Berechnung der Monate unter Berücksichtigung der Schaltjahre wäre problematisch. Wie genau muss das sein?
Dbasnett
mögliches Duplikat von Wie berechne ich die relative Zeit?
Cole Johnson

Antworten:

527

Verwenden Sie dies für Legacy-Code (PHP <5.3). Für eine aktuelle Lösung siehe Jurkas Antwort unten

Mit strtotime () können Sie zwei Daten in Unix-Zeit konvertieren und dann die Anzahl der Sekunden zwischen ihnen berechnen. Daraus ist es ziemlich einfach, verschiedene Zeiträume zu berechnen.

$date1 = "2007-03-24";
$date2 = "2009-06-26";

$diff = abs(strtotime($date2) - strtotime($date1));

$years = floor($diff / (365*60*60*24));
$months = floor(($diff - $years * 365*60*60*24) / (30*60*60*24));
$days = floor(($diff - $years * 365*60*60*24 - $months*30*60*60*24)/ (60*60*24));

printf("%d years, %d months, %d days\n", $years, $months, $days);

Bearbeiten: Offensichtlich ist die bevorzugte Methode dies wie von Jurka unten beschrieben. Mein Code wird im Allgemeinen nur empfohlen, wenn Sie nicht über PHP 5.3 oder besser verfügen.

Mehrere Personen in den Kommentaren haben darauf hingewiesen, dass der obige Code nur eine Annäherung ist. Ich glaube immer noch, dass dies für die meisten Zwecke in Ordnung ist, da die Verwendung eines Bereichs eher dazu dient, ein Gefühl dafür zu vermitteln, wie viel Zeit vergangen ist oder verbleibt, als um Präzision zu gewährleisten. Wenn Sie dies tun möchten, geben Sie einfach das Datum aus.

Trotz alledem habe ich mich entschlossen, die Beschwerden anzusprechen. Wenn Sie wirklich einen genauen Bereich benötigen, aber keinen Zugriff auf PHP 5.3 haben, verwenden Sie den folgenden Code (er sollte auch in PHP 4 funktionieren). Dies ist ein direkter Port des Codes, den PHP intern zur Berechnung von Bereichen verwendet, mit der Ausnahme, dass die Sommerzeit nicht berücksichtigt wird. Das bedeutet, dass es höchstens eine Stunde dauert, aber ansonsten sollte es korrekt sein.

<?php

/**
 * Calculate differences between two dates with precise semantics. Based on PHPs DateTime::diff()
 * implementation by Derick Rethans. Ported to PHP by Emil H, 2011-05-02. No rights reserved.
 * 
 * See here for original code:
 * http://svn.php.net/viewvc/php/php-src/trunk/ext/date/lib/tm2unixtime.c?revision=302890&view=markup
 * http://svn.php.net/viewvc/php/php-src/trunk/ext/date/lib/interval.c?revision=298973&view=markup
 */

function _date_range_limit($start, $end, $adj, $a, $b, $result)
{
    if ($result[$a] < $start) {
        $result[$b] -= intval(($start - $result[$a] - 1) / $adj) + 1;
        $result[$a] += $adj * intval(($start - $result[$a] - 1) / $adj + 1);
    }

    if ($result[$a] >= $end) {
        $result[$b] += intval($result[$a] / $adj);
        $result[$a] -= $adj * intval($result[$a] / $adj);
    }

    return $result;
}

function _date_range_limit_days($base, $result)
{
    $days_in_month_leap = array(31, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);
    $days_in_month = array(31, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);

    _date_range_limit(1, 13, 12, "m", "y", &$base);

    $year = $base["y"];
    $month = $base["m"];

    if (!$result["invert"]) {
        while ($result["d"] < 0) {
            $month--;
            if ($month < 1) {
                $month += 12;
                $year--;
            }

            $leapyear = $year % 400 == 0 || ($year % 100 != 0 && $year % 4 == 0);
            $days = $leapyear ? $days_in_month_leap[$month] : $days_in_month[$month];

            $result["d"] += $days;
            $result["m"]--;
        }
    } else {
        while ($result["d"] < 0) {
            $leapyear = $year % 400 == 0 || ($year % 100 != 0 && $year % 4 == 0);
            $days = $leapyear ? $days_in_month_leap[$month] : $days_in_month[$month];

            $result["d"] += $days;
            $result["m"]--;

            $month++;
            if ($month > 12) {
                $month -= 12;
                $year++;
            }
        }
    }

    return $result;
}

function _date_normalize($base, $result)
{
    $result = _date_range_limit(0, 60, 60, "s", "i", $result);
    $result = _date_range_limit(0, 60, 60, "i", "h", $result);
    $result = _date_range_limit(0, 24, 24, "h", "d", $result);
    $result = _date_range_limit(0, 12, 12, "m", "y", $result);

    $result = _date_range_limit_days(&$base, &$result);

    $result = _date_range_limit(0, 12, 12, "m", "y", $result);

    return $result;
}

/**
 * Accepts two unix timestamps.
 */
function _date_diff($one, $two)
{
    $invert = false;
    if ($one > $two) {
        list($one, $two) = array($two, $one);
        $invert = true;
    }

    $key = array("y", "m", "d", "h", "i", "s");
    $a = array_combine($key, array_map("intval", explode(" ", date("Y m d H i s", $one))));
    $b = array_combine($key, array_map("intval", explode(" ", date("Y m d H i s", $two))));

    $result = array();
    $result["y"] = $b["y"] - $a["y"];
    $result["m"] = $b["m"] - $a["m"];
    $result["d"] = $b["d"] - $a["d"];
    $result["h"] = $b["h"] - $a["h"];
    $result["i"] = $b["i"] - $a["i"];
    $result["s"] = $b["s"] - $a["s"];
    $result["invert"] = $invert ? 1 : 0;
    $result["days"] = intval(abs(($one - $two)/86400));

    if ($invert) {
        _date_normalize(&$a, &$result);
    } else {
        _date_normalize(&$b, &$result);
    }

    return $result;
}

$date = "1986-11-10 19:37:22";

print_r(_date_diff(strtotime($date), time()));
print_r(_date_diff(time(), strtotime($date)));
Emil H.
quelle
1
Wenn Sie die DateTime-Klasse verwenden, können Sie das Format $ date-> ('U') wählen, um den Unix-Zeitstempel abzurufen.
Jon Cram
4
Es ist nicht wahr, wenn Sie sich mit Sommer / Winter beschäftigen müssen. In diesem speziellen Fall entspricht ein Tag 23 oder 25 Stunden, wenn Sie die Sommer- / Winterzeit anpassen.
Arno
4
Nun, das gleiche Argument könnte für Schaltjahre gemacht werden. Das wird auch nicht berücksichtigt. Trotzdem bin ich nicht davon überzeugt, dass Sie dies überhaupt berücksichtigen möchten, da wir hier einen Bereich diskutieren. Die Semantik für einen Bereich ist etwas anders als für ein absolutes Datum.
Emil H
9
Diese Funktion ist falsch. Es ist gut für eine Annäherung, aber falsch für genaue Bereiche. Zum einen wird davon ausgegangen, dass ein Monat 30 Tage hat, was bedeutet, dass zwischen dem 1. Februar und dem 1. März die gleiche Tagesdifferenz besteht wie zwischen dem 1. Juli und dem 1. August (unabhängig vom Schaltjahr).
Enobrev
1
In PHP befinden sich Referenzvariablen in der Funktionssignatur, nicht im Aufruf. Bewegen Sie alle Ihre &zu den Unterschriften.
Paul Tarjan
909

Ich schlage vor, DateTime- und DateInterval-Objekte zu verwenden.

$date1 = new DateTime("2007-03-24");
$date2 = new DateTime("2009-06-26");
$interval = $date1->diff($date2);
echo "difference " . $interval->y . " years, " . $interval->m." months, ".$interval->d." days "; 

// shows the total amount of days (not divided into years, months and days like above)
echo "difference " . $interval->days . " days ";

Lesen Sie mehr PHP DateTime :: Diff Handbuch

Aus dem Handbuch:

Ab PHP 5.2.2 können DateTime-Objekte mit Vergleichsoperatoren verglichen werden.

$date1 = new DateTime("now");
$date2 = new DateTime("tomorrow");

var_dump($date1 == $date2); // bool(false)
var_dump($date1 < $date2);  // bool(true)
var_dump($date1 > $date2);  // bool(false)
jurka
quelle
14
+1 DateTime behandelt Schaltjahre und Zeitzonen richtig und es gibt ein gutes Buch für das Regal: phparch.com/books/…
hakre
3
Gibt es eine Methode, die die Gesamtzahl der Sekunden zwischen den beiden DateTimes angibt? (ohne die Komponenten zu addieren, das heißt)
Kartoffel
1
@Panique Die $ Intervall-> Tage und $ Intervall-> d sind verschiedene Maße. Ihr Kommentar oben ist richtig "zeigt die Gesamtzahl der Tage (nicht in Jahre, Monate und Tage wie oben unterteilt)"
Jurka
1
@potatoe Du willst wahrscheinlich $date2->format('U') - $date1->format('U').
Paulo Freitas
3
Beachten Sie, dass es einen Fehler gibt, bei dem DateInterval unter Windows mit einigen PHP-Versionen eine falsche Days-Eigenschaft ( immer 6015 ) hat: bugs.php.net/bug.php?id=51184 ( Fehlerbehebung / Problemumgehung finden Sie in den Kommentaren)
Pim Schaaf
73

Die beste Vorgehensweise ist die Verwendung der DateTime(und DateInterval) Objekte von PHP . Jedes Datum ist in einem DateTimeObjekt gekapselt , und dann kann ein Unterschied zwischen den beiden gemacht werden:

$first_date = new DateTime("2012-11-30 17:03:30");
$second_date = new DateTime("2012-12-21 00:00:00");

Das DateTimeObjekt akzeptiert jedes Format strtotime(). Wenn ein noch spezifischeres Datumsformat benötigt wird, DateTime::createFromFormat()kann es zum Erstellen des DateTimeObjekts verwendet werden.

Nachdem beide Objekte instanziiert wurden, subtrahieren Sie mit DateTime::diff().

$difference = $first_date->diff($second_date);

$differencehält jetzt ein DateIntervalObjekt mit den Differenzinformationen. A var_dump()sieht so aus:

object(DateInterval)
  public 'y' => int 0
  public 'm' => int 0
  public 'd' => int 20
  public 'h' => int 6
  public 'i' => int 56
  public 's' => int 30
  public 'invert' => int 0
  public 'days' => int 20

Um das DateIntervalObjekt zu formatieren , müssen wir jeden Wert überprüfen und ausschließen, wenn er 0 ist:

/**
 * Format an interval to show all existing components.
 * If the interval doesn't have a time component (years, months, etc)
 * That component won't be displayed.
 *
 * @param DateInterval $interval The interval
 *
 * @return string Formatted interval string.
 */
function format_interval(DateInterval $interval) {
    $result = "";
    if ($interval->y) { $result .= $interval->format("%y years "); }
    if ($interval->m) { $result .= $interval->format("%m months "); }
    if ($interval->d) { $result .= $interval->format("%d days "); }
    if ($interval->h) { $result .= $interval->format("%h hours "); }
    if ($interval->i) { $result .= $interval->format("%i minutes "); }
    if ($interval->s) { $result .= $interval->format("%s seconds "); }

    return $result;
}

Jetzt müssen wir nur noch unsere Funktion für das $difference DateIntervalObjekt aufrufen :

echo format_interval($difference);

Und wir bekommen das richtige Ergebnis:

20 Tage 6 Stunden 56 Minuten 30 Sekunden

Der vollständige Code zur Erreichung des Ziels:

/**
 * Format an interval to show all existing components.
 * If the interval doesn't have a time component (years, months, etc)
 * That component won't be displayed.
 *
 * @param DateInterval $interval The interval
 *
 * @return string Formatted interval string.
 */
function format_interval(DateInterval $interval) {
    $result = "";
    if ($interval->y) { $result .= $interval->format("%y years "); }
    if ($interval->m) { $result .= $interval->format("%m months "); }
    if ($interval->d) { $result .= $interval->format("%d days "); }
    if ($interval->h) { $result .= $interval->format("%h hours "); }
    if ($interval->i) { $result .= $interval->format("%i minutes "); }
    if ($interval->s) { $result .= $interval->format("%s seconds "); }

    return $result;
}

$first_date = new DateTime("2012-11-30 17:03:30");
$second_date = new DateTime("2012-12-21 00:00:00");

$difference = $first_date->diff($second_date);

echo format_interval($difference);
Madaras Geist
quelle
DateTime()ist keine Funktion, es ist ein Objekt und es ist da seit PHP 5.2. Stellen Sie sicher, dass Ihr Server dies unterstützt.
Madaras Geist
2
@SecondRikudo DateTime :: Diff braucht PHP 5.3.0
PhoneixS
Wir haben ein Problem, tauschen Sie first_date gegen second_date aus und wir erhalten das gleiche Ergebnis? Warum nicht 0 Tage 0 Stunden 0 Minuten 0 Sekunden oder nur 0 sagen? Beispiel: 2012-11-30 17:03:30 - 2012-12-21 00:00:00 und 2012-12-21 00:00:00 - 2012-11-30 17:03:30 erhalten das gleiche Ergebnis.
EgoistDeveloper
Weil diff Ihnen den Unterschied zwischen den beiden Zeiten gibt. Die Differenz ist nicht 0, unabhängig davon, welches Datum später kommt.
Madaras Geist
1
Dies ist eine wirklich gute Antwort, da sie eine klare Funktion bietet, die von überall in einer Codebasis ohne viel Zeitaufwand aufgerufen werden kann. Andere Antworten ermöglichen es Ihnen, Echo-Berechnungen im laufenden Betrieb zu löschen, die die Symptome beheben, anstatt das Problem zu lösen ... Das einzige Element, das ich hinzugefügt habe (und so ziemlich alle anderen Beiträge behandeln dies nicht), ist die Pluralisierung von $ -Intervall-Elementen wenn mehr als 1.
Nickhar
33

Stunden und Minuten und Sekunden anzeigen ..

$date1 = "2008-11-01 22:45:00"; 

$date2 = "2009-12-04 13:44:01"; 

$diff = abs(strtotime($date2) - strtotime($date1)); 

$years   = floor($diff / (365*60*60*24)); 
$months  = floor(($diff - $years * 365*60*60*24) / (30*60*60*24)); 
$days    = floor(($diff - $years * 365*60*60*24 - $months*30*60*60*24)/ (60*60*24));

$hours   = floor(($diff - $years * 365*60*60*24 - $months*30*60*60*24 - $days*60*60*24)/ (60*60)); 

$minuts  = floor(($diff - $years * 365*60*60*24 - $months*30*60*60*24 - $days*60*60*24 - $hours*60*60)/ 60); 

$seconds = floor(($diff - $years * 365*60*60*24 - $months*30*60*60*24 - $days*60*60*24 - $hours*60*60 - $minuts*60)); 

printf("%d years, %d months, %d days, %d hours, %d minuts\n, %d seconds\n", $years, $months, $days, $hours, $minuts, $seconds); 
Khaldonno
quelle
7
Wahrscheinlich liefert dies nicht das genaue Ergebnis.
Delphin
8
Und ist eine schreckliche Lösung, es sei denn, Sie sind gezwungen, eine schrecklich veraltete Version von PHP zu verwenden ...
Rdlowrey
2
Nicht so trocken . Zum Beispiel wird 60 * 60 * 24 15 Mal wiederholt. Es lebe die Wiederverwendung durch Kopieren und Einfügen!
Peter Mortensen
Was ist mit Schaltjahren? Ein Jahr ist im Durchschnitt nicht 365 Tage.
Peter Mortensen
Dieser Code geht davon aus, dass ein Monat durchschnittlich 30 Tage beträgt. Selbst wenn 365 Tage für ein Jahr angenommen werden, beträgt ein durchschnittlicher Monat 365/12 = 30,42 Tage (ungefähr).
Peter Mortensen
18

Schauen Sie sich den folgenden Link an. Dies ist die beste Antwort, die ich bisher gefunden habe .. :)

function dateDiff ($d1, $d2) {

    // Return the number of days between the two dates:    
    return round(abs(strtotime($d1) - strtotime($d2))/86400);

} // end function dateDiff

Es spielt keine Rolle, welches Datum früher oder später liegt, wenn Sie die Datumsparameter übergeben. Die Funktion verwendet den PHP ABS () - Absolutwert, um immer eine positive Zahl als Anzahl der Tage zwischen den beiden Daten zurückzugeben.

Beachten Sie, dass die Anzahl der Tage zwischen den beiden Daten NICHT beide Daten enthält. Wenn Sie also nach der Anzahl der Tage suchen, die durch alle Daten zwischen und einschließlich der eingegebenen Daten dargestellt werden, müssen Sie dem Ergebnis dieser Funktion eine (1) hinzufügen.

Beispielsweise beträgt die Differenz (wie von der obigen Funktion zurückgegeben) zwischen 2013-02-09 und 2013-02-14 5. Die Anzahl der Tage oder Daten wird jedoch durch den Datumsbereich 2013-02-09 - 2013-02- dargestellt. 14 ist 6.

http://www.bizinfosys.com/php/date-difference.html

casper123
quelle
Bei der Frage wurde nach dem Unterschied als Anzahl der Jahre, Monate und Tage gefragt, nicht nach der Gesamtzahl der Tage.
Peter Mortensen
14

Ich habe für jurka ‚s Antwort wie mein Favorit ist, aber ich habe eine Pre-php.5.3 Version ...

Ich habe an einem ähnlichen Problem gearbeitet - so kam ich überhaupt zu dieser Frage -, brauchte aber nur einen Unterschied in Stunden. Aber meine Funktion hat dieses Problem auch ziemlich gut gelöst und ich habe nirgendwo in meiner eigenen Bibliothek, wo ich es aufbewahren kann, wo es nicht verloren geht und vergessen wird. Ich hoffe, dass dies für jemanden nützlich ist.

/**
 *
 * @param DateTime $oDate1
 * @param DateTime $oDate2
 * @return array 
 */
function date_diff_array(DateTime $oDate1, DateTime $oDate2) {
    $aIntervals = array(
        'year'   => 0,
        'month'  => 0,
        'week'   => 0,
        'day'    => 0,
        'hour'   => 0,
        'minute' => 0,
        'second' => 0,
    );

    foreach($aIntervals as $sInterval => &$iInterval) {
        while($oDate1 <= $oDate2){ 
            $oDate1->modify('+1 ' . $sInterval);
            if ($oDate1 > $oDate2) {
                $oDate1->modify('-1 ' . $sInterval);
                break;
            } else {
                $iInterval++;
            }
        }
    }

    return $aIntervals;
}

Und der Test:

$oDate = new DateTime();
$oDate->modify('+111402189 seconds');
var_dump($oDate);
var_dump(date_diff_array(new DateTime(), $oDate));

Und das Ergebnis:

object(DateTime)[2]
  public 'date' => string '2014-04-29 18:52:51' (length=19)
  public 'timezone_type' => int 3
  public 'timezone' => string 'America/New_York' (length=16)

array
  'year'   => int 3
  'month'  => int 6
  'week'   => int 1
  'day'    => int 4
  'hour'   => int 9
  'minute' => int 3
  'second' => int 8

Ich habe die ursprüngliche Idee von hier , die ich für meine Anwendungen modifizierte (und ich hoffe , meine Änderung auf dieser Seite zeigt auch).

Sie können Intervalle, die Sie nicht möchten (z. B. "Woche"), sehr einfach entfernen, indem Sie sie aus dem $aIntervalsArray entfernen oder einen $aExcludeParameter hinzufügen oder sie einfach herausfiltern, wenn Sie die Zeichenfolge ausgeben.

enobrev
quelle
Leider gibt dies aufgrund von Jahres- / Monatsüberläufen nicht dasselbe wie DateInterval zurück.
Stephen Harris
2
@StephenHarris: Ich habe dies nicht getestet, aber beim Lesen des Codes bin ich ziemlich sicher, dass es das gleiche Ergebnis zurückgeben sollte - vorausgesetzt, Sie löschen den weekIndex in $aIntervals(da dies DateDiffnie verwendet wird).
Alix Axel
Dies ist eine großartige Lösung, um Daten zu finden, die in jedem Intervall zwischen zwei Daten auftreten.
Zwischen Gehirn
14
<?php
    $today = strtotime("2011-02-03 00:00:00");
    $myBirthDate = strtotime("1964-10-30 00:00:00");
    printf("Days since my birthday: ", ($today - $myBirthDate)/60/60/24);
?>
vengat
quelle
Die Frage stellte den Unterschied als Anzahl der Jahre , Monate und Tage . Dies gibt die Differenz als Gesamtzahl der Tage aus.
Peter Mortensen
11

Ich weiß nicht, ob Sie ein PHP-Framework verwenden oder nicht, aber viele PHP-Frameworks verfügen über Datums- / Zeitbibliotheken und Helfer, die Sie davon abhalten, das Rad neu zu erfinden.

Zum Beispiel hat CodeIgniter die timespan()Funktion. Geben Sie einfach zwei Unix-Zeitstempel ein und es wird automatisch ein Ergebnis wie das folgende generiert:

1 Year, 10 Months, 2 Weeks, 5 Days, 10 Hours, 16 Minutes

http://codeigniter.com/user_guide/helpers/date_helper.html

Jake Wilson
quelle
8

Anwendungsbeispiel:

echo time_diff_string('2013-05-01 00:22:35', 'now');
echo time_diff_string('2013-05-01 00:22:35', 'now', true);

Ausgabe :

4 months ago
4 months, 2 weeks, 3 days, 1 hour, 49 minutes, 15 seconds ago

Funktion:

function time_diff_string($from, $to, $full = false) {
    $from = new DateTime($from);
    $to = new DateTime($to);
    $diff = $to->diff($from);

    $diff->w = floor($diff->d / 7);
    $diff->d -= $diff->w * 7;

    $string = array(
        'y' => 'year',
        'm' => 'month',
        'w' => 'week',
        'd' => 'day',
        'h' => 'hour',
        'i' => 'minute',
        's' => 'second',
    );
    foreach ($string as $k => &$v) {
        if ($diff->$k) {
            $v = $diff->$k . ' ' . $v . ($diff->$k > 1 ? 's' : '');
        } else {
            unset($string[$k]);
        }
    }

    if (!$full) $string = array_slice($string, 0, 1);
    return $string ? implode(', ', $string) . ' ago' : 'just now';
}
Glavić
quelle
Was soll ich tun, wenn ich feststellen möchte, ob der Unterschied größer als 30 Minuten ist?
Ofir Attia
@OfirAttia: Sie haben eine Reihe solcher Fragen hier auf SO, verwenden Sie einfach die Suche. Einfache Demo
Glavić
7

Ich habe eine einfache Logik dafür:

<?php
    per_days_diff('2011-12-12','2011-12-29')
    function per_days_diff($start_date, $end_date) {
        $per_days = 0;
        $noOfWeek = 0;
        $noOfWeekEnd = 0;
        $highSeason=array("7", "8");

        $current_date = strtotime($start_date);
        $current_date += (24 * 3600);
        $end_date = strtotime($end_date);

        $seassion = (in_array(date('m', $current_date), $highSeason))?"2":"1";

        $noOfdays = array('');

        while ($current_date <= $end_date) {
            if ($current_date <= $end_date) {
                $date = date('N', $current_date);
                array_push($noOfdays,$date);
                $current_date = strtotime('+1 day', $current_date);
            }
        }

        $finalDays = array_shift($noOfdays);
        //print_r($noOfdays);
        $weekFirst = array("week"=>array(),"weekEnd"=>array());
        for($i = 0; $i < count($noOfdays); $i++)
        {
            if ($noOfdays[$i] == 1)
            {
                //echo "This is week";
                //echo "<br/>";
                if($noOfdays[$i+6]==7)
                {
                    $noOfWeek++;
                    $i=$i+6;
                }
                else
                {
                    $per_days++;
                }
                //array_push($weekFirst["week"],$day);
            }
            else if($noOfdays[$i]==5)
            {
                //echo "This is weekend";
                //echo "<br/>";
                if($noOfdays[$i+2] ==7)
                {
                    $noOfWeekEnd++;
                    $i = $i+2;
                }
                else
                {
                    $per_days++;
                }
                //echo "After weekend value:- ".$i;
                //echo "<br/>";
            }
            else
            {
                $per_days++;
            }
        }

        /*echo $noOfWeek;
          echo "<br/>";
          echo $noOfWeekEnd;
          echo "<br/>";
          print_r($per_days);
          echo "<br/>";
          print_r($weekFirst);
        */

        $duration = array("weeks"=>$noOfWeek, "weekends"=>$noOfWeekEnd, "perDay"=>$per_days, "seassion"=>$seassion);
        return $duration;
      ?>
Hardik Raval
quelle
Am Ende des Beispielcodes scheint etwas zu fehlen (eine Endklammer und " ?> "?).
Peter Mortensen
"einfache" Logik. Dies sind mindestens 40 Zeilen reinen Codes.
Madjosz
6

Du kannst den ... benutzen

getdate()

Funktion, die ein Array zurückgibt, das alle Elemente des angegebenen Datums / der angegebenen Uhrzeit enthält:

$diff = abs($endDate - $startDate);
$my_t=getdate($diff);
print("$my_t[year] years, $my_t[month] months and $my_t[mday] days");

Wenn Ihre Start- und Enddaten im Zeichenfolgenformat vorliegen, verwenden Sie

$startDate = strtotime($startDateStr);
$endDate = strtotime($endDateStr);

vor dem obigen Code

Mark Pim
quelle
scheint nicht zu funktionieren. Ich bekomme ein Date zu Beginn der Zeitstempel-Ära.
Sirber
Es ist wichtig zu verstehen, dass Sie eine durchführen müssen $my_t["year"] -= 1970, um die richtige Anzahl von Jahren zu erhalten. Sie müssen auch Ihre Stundendifferenz von GMT abziehen , um die richtigen Stunden zu erhalten. Sie müssen auch 1 von Monat und Datum abziehen.
Salman A
6
// If you just want to see the year difference then use this function.
// Using the logic I've created you may also create month and day difference
// which I did not provide here so you may have the efforts to use your brain.
// :)
$date1='2009-01-01';
$date2='2010-01-01';
echo getYearDifference ($date1,$date2);
function getYearDifference($date1=strtotime($date1),$date2=strtotime($date2)){
    $year = 0;
    while($date2 > $date1 = strtotime('+1 year', $date1)){
        ++$year;
    }
    return $year;
}
Esc
quelle
Berücksichtigt "strtotime ('+ 1 Jahr', $ date1)" Schaltjahre?
Peter Mortensen
6

Das ist meine Funktion. Erforderliches PHP> = 5.3.4. Es wird die DateTime-Klasse verwendet. Sehr schnell, schnell und kann den Unterschied zwischen zwei Daten oder sogar der sogenannten "Zeit seit" machen.

if(function_exists('grk_Datetime_Since') === FALSE){
    function grk_Datetime_Since($From, $To='', $Prefix='', $Suffix=' ago', $Words=array()){
        #   Est-ce qu'on calcul jusqu'à un moment précis ? Probablement pas, on utilise maintenant
        if(empty($To) === TRUE){
            $To = time();
        }

        #   On va s'assurer que $From est numérique
        if(is_int($From) === FALSE){
            $From = strtotime($From);
        };

        #   On va s'assurer que $To est numérique
        if(is_int($To) === FALSE){
            $To = strtotime($To);
        }

        #   On a une erreur ?
        if($From === FALSE OR $From === -1 OR $To === FALSE OR $To === -1){
            return FALSE;
        }

        #   On va créer deux objets de date
        $From = new DateTime(@date('Y-m-d H:i:s', $From), new DateTimeZone('GMT'));
        $To   = new DateTime(@date('Y-m-d H:i:s', $To), new DateTimeZone('GMT'));

        #   On va calculer la différence entre $From et $To
        if(($Diff = $From->diff($To)) === FALSE){
            return FALSE;
        }

        #   On va merger le tableau des noms (par défaut, anglais)
        $Words = array_merge(array(
            'year'      => 'year',
            'years'     => 'years',
            'month'     => 'month',
            'months'    => 'months',
            'week'      => 'week',
            'weeks'     => 'weeks',
            'day'       => 'day',
            'days'      => 'days',
            'hour'      => 'hour',
            'hours'     => 'hours',
            'minute'    => 'minute',
            'minutes'   => 'minutes',
            'second'    => 'second',
            'seconds'   => 'seconds'
        ), $Words);

        #   On va créer la chaîne maintenant
        if($Diff->y > 1){
            $Text = $Diff->y.' '.$Words['years'];
        } elseif($Diff->y == 1){
            $Text = '1 '.$Words['year'];
        } elseif($Diff->m > 1){
            $Text = $Diff->m.' '.$Words['months'];
        } elseif($Diff->m == 1){
            $Text = '1 '.$Words['month'];
        } elseif($Diff->d > 7){
            $Text = ceil($Diff->d/7).' '.$Words['weeks'];
        } elseif($Diff->d == 7){
            $Text = '1 '.$Words['week'];
        } elseif($Diff->d > 1){
            $Text = $Diff->d.' '.$Words['days'];
        } elseif($Diff->d == 1){
            $Text = '1 '.$Words['day'];
        } elseif($Diff->h > 1){
            $Text = $Diff->h.' '.$Words['hours'];
        } elseif($Diff->h == 1){
            $Text = '1 '.$Words['hour'];
        } elseif($Diff->i > 1){
            $Text = $Diff->i.' '.$Words['minutes'];
        } elseif($Diff->i == 1){
            $Text = '1 '.$Words['minute'];
        } elseif($Diff->s > 1){
            $Text = $Diff->s.' '.$Words['seconds'];
        } else {
            $Text = '1 '.$Words['second'];
        }

        return $Prefix.$Text.$Suffix;
    }
}
David Bélanger
quelle
6

Ich würde es vorziehen , Verwendung date_createund date_diffObjekte.

Code:

$date1 = date_create("2007-03-24");
$date2 = date_create("2009-06-26");

$dateDifference = date_diff($date1, $date2)->format('%y years, %m months and %d days');

echo $dateDifference;

Ausgabe:

2 years, 3 months and 2 days

Weitere Informationen finden Sie im PHP- date_diffHandbuch

Laut Handbuch date_diffist ein Alias ​​von DateTime :: diff ()

Adeel
quelle
5

Dadurch wird versucht festzustellen, ob ein Zeitstempel angegeben wurde oder nicht, und es werden auch zukünftige Daten / Zeiten als negative Werte zurückgegeben:

<?php

function time_diff($start, $end = NULL, $convert_to_timestamp = FALSE) {
  // If $convert_to_timestamp is not explicitly set to TRUE,
  // check to see if it was accidental:
  if ($convert_to_timestamp || !is_numeric($start)) {
    // If $convert_to_timestamp is TRUE, convert to timestamp:
    $timestamp_start = strtotime($start);
  }
  else {
    // Otherwise, leave it as a timestamp:
    $timestamp_start = $start;
  }
  // Same as above, but make sure $end has actually been overridden with a non-null,
  // non-empty, non-numeric value:
  if (!is_null($end) && (!empty($end) && !is_numeric($end))) {
    $timestamp_end = strtotime($end);
  }
  else {
    // If $end is NULL or empty and non-numeric value, assume the end time desired
    // is the current time (useful for age, etc):
    $timestamp_end = time();
  }
  // Regardless, set the start and end times to an integer:
  $start_time = (int) $timestamp_start;
  $end_time = (int) $timestamp_end;

  // Assign these values as the params for $then and $now:
  $start_time_var = 'start_time';
  $end_time_var = 'end_time';
  // Use this to determine if the output is positive (time passed) or negative (future):
  $pos_neg = 1;

  // If the end time is at a later time than the start time, do the opposite:
  if ($end_time <= $start_time) {
    $start_time_var = 'end_time';
    $end_time_var = 'start_time';
    $pos_neg = -1;
  }

  // Convert everything to the proper format, and do some math:
  $then = new DateTime(date('Y-m-d H:i:s', $$start_time_var));
  $now = new DateTime(date('Y-m-d H:i:s', $$end_time_var));

  $years_then = $then->format('Y');
  $years_now = $now->format('Y');
  $years = $years_now - $years_then;

  $months_then = $then->format('m');
  $months_now = $now->format('m');
  $months = $months_now - $months_then;

  $days_then = $then->format('d');
  $days_now = $now->format('d');
  $days = $days_now - $days_then;

  $hours_then = $then->format('H');
  $hours_now = $now->format('H');
  $hours = $hours_now - $hours_then;

  $minutes_then = $then->format('i');
  $minutes_now = $now->format('i');
  $minutes = $minutes_now - $minutes_then;

  $seconds_then = $then->format('s');
  $seconds_now = $now->format('s');
  $seconds = $seconds_now - $seconds_then;

  if ($seconds < 0) {
    $minutes -= 1;
    $seconds += 60;
  }
  if ($minutes < 0) {
    $hours -= 1;
    $minutes += 60;
  }
  if ($hours < 0) {
    $days -= 1;
    $hours += 24;
  }
  $months_last = $months_now - 1;
  if ($months_now == 1) {
    $years_now -= 1;
    $months_last = 12;
  }

  // "Thirty days hath September, April, June, and November" ;)
  if ($months_last == 9 || $months_last == 4 || $months_last == 6 || $months_last == 11) {
    $days_last_month = 30;
  }
  else if ($months_last == 2) {
    // Factor in leap years:
    if (($years_now % 4) == 0) {
      $days_last_month = 29;
    }
    else {
      $days_last_month = 28;
    }
  }
  else {
    $days_last_month = 31;
  }
  if ($days < 0) {
    $months -= 1;
    $days += $days_last_month;
  }
  if ($months < 0) {
    $years -= 1;
    $months += 12;
  }

  // Finally, multiply each value by either 1 (in which case it will stay the same),
  // or by -1 (in which case it will become negative, for future dates).
  // Note: 0 * 1 == 0 * -1 == 0
  $out = new stdClass;
  $out->years = (int) $years * $pos_neg;
  $out->months = (int) $months * $pos_neg;
  $out->days = (int) $days * $pos_neg;
  $out->hours = (int) $hours * $pos_neg;
  $out->minutes = (int) $minutes * $pos_neg;
  $out->seconds = (int) $seconds * $pos_neg;
  return $out;
}

Anwendungsbeispiel:

<?php
  $birthday = 'June 2, 1971';
  $check_age_for_this_date = 'June 3, 1999 8:53pm';
  $age = time_diff($birthday, $check_age_for_this_date)->years;
  print $age;// 28

Oder:

<?php
  $christmas_2020 = 'December 25, 2020';
  $countdown = time_diff($christmas_2020);
  print_r($countdown);
Jerdiggity
quelle
5

"Wenn" das Datum in MySQL gespeichert ist, fällt es mir leichter, die Differenzberechnung auf Datenbankebene durchzuführen.

mysql> select firstName, convert_tz(loginDate, '+00:00', '-04:00') as loginDate, TIMESTAMPDIFF(DAY, loginDate, now()) as 'Day', TIMESTAMPDIFF(HOUR, loginDate, now())+4 as 'Hour', TIMESTAMPDIFF(MINUTE, loginDate, now())+(60*4) as 'Min', TIMESTAMPDIFF(SECOND, loginDate, now())+(60*60*4) as 'Sec' from User_ where userId != '10158' AND userId != '10198' group by emailAddress order by loginDate desc;
 +-----------+---------------------+------+------+------+--------+
 | firstName | loginDate           | Day  | Hour | Min  | Sec    |
 +-----------+---------------------+------+------+------+--------+
 | Peter     | 2014-03-30 18:54:40 |    0 |    4 |  244 |  14644 |
 | Keith     | 2014-03-30 18:54:11 |    0 |    4 |  244 |  14673 |
 | Andres    | 2014-03-28 09:20:10 |    2 |   61 | 3698 | 221914 |
 | Nadeem    | 2014-03-26 09:33:43 |    4 |  109 | 6565 | 393901 |
 +-----------+---------------------+------+------+------+--------+
 4 rows in set (0.00 sec)
ElasticThoughts
quelle
5

Ich habe Ihren Artikel auf der folgenden Seite gefunden, die eine Reihe von Referenzen für PHP- Datums- und Uhrzeitberechnungen enthält.

Berechnen Sie die Differenz zwischen zwei Daten (und der Zeit) mit PHP. Auf der folgenden Seite finden Sie eine Reihe verschiedener Methoden (insgesamt 7) zur Durchführung von Datums- / Zeitberechnungen mit PHP, um den Unterschied in Zeit (Stunden, Munition), Tagen, Monaten oder Jahren zwischen zwei Daten zu bestimmen.

Siehe PHP Date Time - 7 Methoden zur Berechnung der Differenz zwischen zwei Daten .

James - Php Entwicklung
quelle
4

Sie können auch den folgenden Code verwenden, um Datumsunterschiede nach runden Brüchen zurückzugeben. $ Date1 = $ duedate; // Fälligkeitsdatum zuweisen echo $ date2 = date ("Ymd"); // aktuelles Datum $ ts1 = strtotime ($ date1); $ ts2 = strtotime ($ date2); $ Sekunden_diff = $ ts1 - $ ts2; echo $ datiertiff = Ceil (($ Sekunden_Diff / 3600) / 24); // in Tagen zurückkehren

Wenn Sie die Bodenmethode von PHP anstelle von Ceil verwenden, erhalten Sie den runden Bruch nach unten. Überprüfen Sie den Unterschied hier. Wenn sich die Zeitzone Ihres Staging-Servers von der Zeitzone der Live-Site unterscheidet, erhalten Sie möglicherweise andere Ergebnisse. Ändern Sie daher die Bedingungen entsprechend.

Rikin Adhyapak
quelle
4
$date1 = date_create('2007-03-24');
$date2 = date_create('2009-06-26');
$interval = date_diff($date1, $date2);
echo "difference : " . $interval->y . " years, " . $interval->m." months, ".$interval->d." days ";
Liza
quelle
4

Sie können immer die folgende Funktion verwenden, die das Alter in Jahren und Monaten (dh 1 Jahr 4 Monate) zurückgeben kann.

function getAge($dob, $age_at_date)
{  
    $d1 = new DateTime($dob);
    $d2 = new DateTime($age_at_date);
    $age = $d2->diff($d1);
    $years = $age->y;
    $months = $age->m;

    return $years.'.'.months;
}

oder wenn Sie möchten, dass das Alter zum aktuellen Datum berechnet wird, können Sie verwenden

function getAge($dob)
{  
    $d1 = new DateTime($dob);
    $d2 = new DateTime(date());
    $age = $d2->diff($d1);
    $years = $age->y;
    $months = $age->m;

    return $years.'.'.months;
}
Rickus Harmse
quelle
4

Für PHP-Version> = 5.3: Erstellen Sie zwei Datumsobjekte und verwenden Sie dann die date_diff()Funktion. Es wird ein PHP DateInterval- Objekt zurückgeben. siehe Dokumentation

$date1=date_create("2007-03-24");
$date2=date_create("2009-06-26");
$diff=date_diff($date1,$date2);
echo $diff->format("%R%a days");
bikram kc
quelle
4

Hier ist der ausführbare Code

$date1 = date_create('2007-03-24');
$date2 = date_create('2009-06-26');
$diff1 = date_diff($date1,$date2);
$daysdiff = $diff1->format("%R%a");
$daysdiff = abs($daysdiff);
Mosin
quelle
3

Ich hatte das gleiche Problem mit PHP 5.2 und löste es mit MySQL. Könnte nicht genau das sein, wonach Sie suchen, aber dies reicht aus und gibt die Anzahl der Tage zurück:

$datediff_q = $dbh->prepare("SELECT DATEDIFF(:date2, :date1)");
$datediff_q->bindValue(':date1', '2007-03-24', PDO::PARAM_STR);
$datediff_q->bindValue(':date2', '2009-06-26', PDO::PARAM_STR);
$datediff = ($datediff_q->execute()) ? $datediff_q->fetchColumn(0) : false;

Weitere Informationen finden Sie hier http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html#function_datediff

Klemen Tušar
quelle
3

Da jeder Codebeispiele veröffentlicht, ist hier eine andere Version.

Ich wollte eine Funktion, die Unterschiede von Sekunden bis Jahren anzeigt (nur eine Einheit). Für Zeiträume über 1 Tag wollte ich, dass es um Mitternacht überrollt wird (Montag um 10 Uhr ab 9 Uhr Mittwoch ist vor 2 Tagen, nicht 1). Und für Zeiträume über einen Monat wollte ich, dass der Rollover am selben Tag des Monats stattfindet (einschließlich für 30/31 Tage, Monate und Schaltjahre).

Das habe ich mir ausgedacht:

/**
 * Returns how long ago something happened in the past, showing it
 * as n seconds / minutes / hours / days / weeks / months / years ago.
 *
 * For periods over a day, it rolls over at midnight (so doesn't depend
 * on current time of day), and it correctly accounts for month-lengths
 * and leap-years (months and years rollover on current day of month).
 *
 * $param string $timestamp in DateTime format
 * $return string description of interval
 */
function ago($timestamp)
{
    $then = date_create($timestamp);

    // for anything over 1 day, make it rollover on midnight
    $today = date_create('tomorrow'); // ie end of today
    $diff = date_diff($then, $today);

    if ($diff->y > 0) return $diff->y.' year'.($diff->y>1?'s':'').' ago';
    if ($diff->m > 0) return $diff->m.' month'.($diff->m>1?'s':'').' ago';
    $diffW = floor($diff->d / 7);
    if ($diffW > 0) return $diffW.' week'.($diffW>1?'s':'').' ago';
    if ($diff->d > 1) return $diff->d.' day'.($diff->d>1?'s':'').' ago';

    // for anything less than 1 day, base it off 'now'
    $now = date_create();
    $diff = date_diff($then, $now);

    if ($diff->d > 0) return 'yesterday';
    if ($diff->h > 0) return $diff->h.' hour'.($diff->h>1?'s':'').' ago';
    if ($diff->i > 0) return $diff->i.' minute'.($diff->i>1?'s':'').' ago';
    return $diff->s.' second'.($diff->s==1?'':'s').' ago';
}
ChrisV
quelle
3

Vor einiger Zeit habe ich eine format_dateFunktion geschrieben, da diese viele Optionen bietet, wie Sie Ihr Datum haben möchten :

function format_date($date, $type, $seperator="-")
{
    if($date)
    {
        $day = date("j", strtotime($date));
        $month = date("n", strtotime($date));
        $year = date("Y", strtotime($date));
        $hour = date("H", strtotime($date));
        $min = date("i", strtotime($date));
        $sec = date("s", strtotime($date));

        switch($type)
        {
            case 0:  $date = date("Y".$seperator."m".$seperator."d",mktime($hour, $min, $sec, $month, $day, $year)); break;
            case 1:  $date = date("D, F j, Y",mktime($hour, $min, $sec, $month, $day, $year)); break;
            case 2:  $date = date("d".$seperator."m".$seperator."Y",mktime($hour, $min, $sec, $month, $day, $year)); break;
            case 3:  $date = date("d".$seperator."M".$seperator."Y",mktime($hour, $min, $sec, $month, $day, $year)); break;
            case 4:  $date = date("d".$seperator."M".$seperator."Y h:i A",mktime($hour, $min, $sec, $month, $day, $year)); break;
            case 5:  $date = date("m".$seperator."d".$seperator."Y",mktime($hour, $min, $sec, $month, $day, $year)); break;
            case 6:  $date = date("M",mktime($hour, $min, $sec, $month, $day, $year)); break;
            case 7:  $date = date("Y",mktime($hour, $min, $sec, $month, $day, $year)); break;
            case 8:  $date = date("j",mktime($hour, $min, $sec, $month, $day, $year)); break;
            case 9:  $date = date("n",mktime($hour, $min, $sec, $month, $day, $year)); break;
            case 10: 
                     $diff = abs(strtotime($date) - strtotime(date("Y-m-d h:i:s"))); 
                     $years = floor($diff / (365*60*60*24));
                     $months = floor(($diff - $years * 365*60*60*24) / (30*60*60*24));
                     $days = floor(($diff - $years * 365*60*60*24 - $months*30*60*60*24)/ (60*60*24));
                     $date = $years . " years, " . $months . " months, " . $days . "days";
        }
    }
    return($date);
}    
Champ
quelle
2
Diese Antwort ist genauso falsch wie Khaldonnos Antwort. Es wird angenommen (Fall 10), dass ein Jahr 365 Tage hat (jedes vierte Jahr hat 366 Tage (mit Ausnahme der Regeln für 100 Jahre / 400 Jahre für den Gregorianischen Kalender)) und dass ein Monat 30 Tage hat (es sind ungefähr 30,42 Tage in Nicht-Schaltjahren). Selbst mit besseren Konstanten ist es nur im Durchschnitt korrekt, nicht unbedingt für zwei bestimmte Daten.
Peter Mortensen
3

Sehr einfach:

    <?php
        $date1 = date_create("2007-03-24");
        echo "Start date: ".$date1->format("Y-m-d")."<br>";
        $date2 = date_create("2009-06-26");
        echo "End date: ".$date2->format("Y-m-d")."<br>";
        $diff = date_diff($date1,$date2);
        echo "Difference between start date and end date: ".$diff->format("%y years, %m months and %d days")."<br>";
    ?>

Bitte überprüfen Sie den folgenden Link für Details:

PHP: date_diff - Handbuch

Beachten Sie, dass es für PHP 5.3.0 oder höher ist.

Choudhury Saadmaan Mahmid
quelle
3

Eine einfache Funktion

function time_difference($time_1, $time_2, $limit = null)
{

    $val_1 = new DateTime($time_1);
    $val_2 = new DateTime($time_2);

    $interval = $val_1->diff($val_2);

    $output = array(
        "year" => $interval->y,
        "month" => $interval->m,
        "day" => $interval->d,
        "hour" => $interval->h,
        "minute" => $interval->i,
        "second" => $interval->s
    );

    $return = "";
    foreach ($output AS $key => $value) {

        if ($value == 1)
            $return .= $value . " " . $key . " ";
        elseif ($value >= 1)
            $return .= $value . " " . $key . "s ";

        if ($key == $limit)
            return trim($return);
    }
    return trim($return);
}

Verwenden Sie wie

echo time_difference ($time_1, $time_2, "day");

Ich werde gerne wiederkommen 2 years 8 months 2 days

Anuj
quelle
3

Versuchen Sie diese sehr einfache Antwort mit date_diff () , dies wird getestet.

$date1 = date_create("2017-11-27");
$date2 = date_create("2018-12-29");
$diff=date_diff($date1,$date2);
$months = $diff->format("%m months");
$years = $diff->format("%y years");
$days = $diff->format("%d days");

echo $years .' '.$months.' '.$days;

Die Ausgabe ist:

1 years 1 months 2 days
Larp
quelle
2

Ich verwende die folgende Funktion, die ich geschrieben habe, wenn PHP 5.3 (bzw. date_diff ()) nicht verfügbar ist:

        function dateDifference($startDate, $endDate)
        {
            $startDate = strtotime($startDate);
            $endDate = strtotime($endDate);
            if ($startDate === false || $startDate < 0 || $endDate === false || $endDate < 0 || $startDate > $endDate)
                return false;

            $years = date('Y', $endDate) - date('Y', $startDate);

            $endMonth = date('m', $endDate);
            $startMonth = date('m', $startDate);

            // Calculate months
            $months = $endMonth - $startMonth;
            if ($months <= 0)  {
                $months += 12;
                $years--;
            }
            if ($years < 0)
                return false;

            // Calculate the days
            $measure = ($months == 1) ? 'month' : 'months';
            $days = $endDate - strtotime('+' . $months . ' ' . $measure, $startDate);
            $days = date('z', $days);   

            return array($years, $months, $days);
        }
Konstantin Shegunov
quelle
2

DateInterval ist großartig, hat aber ein paar Einschränkungen:

  1. nur für PHP 5.3+ ( aber das ist wirklich keine gute Entschuldigung mehr )
  2. unterstützt nur Jahre, Monate, Tage, Stunden, Minuten und Sekunden (keine Wochen)
  3. Es berechnet die Differenz mit allen oben genannten + Tagen (Sie können die Differenz nicht nur in Monaten erhalten).

Um dies zu überwinden, habe ich Folgendes codiert (verbessert von der Antwort von @enobrev ):

function date_dif($since, $until, $keys = 'year|month|week|day|hour|minute|second')
{
    $date = array_map('strtotime', array($since, $until));

    if ((count($date = array_filter($date, 'is_int')) == 2) && (sort($date) === true))
    {
        $result = array_fill_keys(explode('|', $keys), 0);

        foreach (preg_grep('~^(?:year|month)~i', $result) as $key => $value)
        {
            while ($date[1] >= strtotime(sprintf('+%u %s', $value + 1, $key), $date[0]))
            {
                ++$value;
            }

            $date[0] = strtotime(sprintf('+%u %s', $result[$key] = $value, $key), $date[0]);
        }

        foreach (preg_grep('~^(?:year|month)~i', $result, PREG_GREP_INVERT) as $key => $value)
        {
            if (($value = intval(abs($date[0] - $date[1]) / strtotime(sprintf('%u %s', 1, $key), 0))) > 0)
            {
                $date[0] = strtotime(sprintf('+%u %s', $result[$key] = $value, $key), $date[0]);
            }
        }

        return $result;
    }

    return false;
}

Es werden zwei Schleifen ausgeführt. Das erste behandelt die relativen Intervalle (Jahre und Monate) durch Brute-Forcing, und das zweite berechnet die zusätzlichen absoluten Intervalle mit einfacher Arithmetik (also schneller):

echo humanize(date_dif('2007-03-24', '2009-07-31', 'second')); // 74300400 seconds
echo humanize(date_dif('2007-03-24', '2009-07-31', 'minute|second')); // 1238400 minutes, 0 seconds
echo humanize(date_dif('2007-03-24', '2009-07-31', 'hour|minute|second')); // 20640 hours, 0 minutes, 0 seconds
echo humanize(date_dif('2007-03-24', '2009-07-31', 'year|day')); // 2 years, 129 days
echo humanize(date_dif('2007-03-24', '2009-07-31', 'year|week')); // 2 years, 18 weeks
echo humanize(date_dif('2007-03-24', '2009-07-31', 'year|week|day')); // 2 years, 18 weeks, 3 days
echo humanize(date_dif('2007-03-24', '2009-07-31')); // 2 years, 4 months, 1 week, 0 days, 0 hours, 0 minutes, 0 seconds

function humanize($array)
{
    $result = array();

    foreach ($array as $key => $value)
    {
        $result[$key] = $value . ' ' . $key;

        if ($value != 1)
        {
            $result[$key] .= 's';
        }
    }

    return implode(', ', $result);
}
Alix Axel
quelle
@PeterMortensen: Es sollte funktionieren, aber ich gebe keine Garantie. Stellen Sie Ihre Zeitzone ein und probieren Sie es aus.
Alix Axel