Ich habe zwei Daten des Formulars:
Start Date: 2007-03-24
End Date: 2009-06-26
Nun muss ich die Differenz zwischen diesen beiden in der folgenden Form finden:
2 years, 3 months and 2 days
Wie kann ich dies in PHP tun?
Ich habe zwei Daten des Formulars:
Start Date: 2007-03-24
End Date: 2009-06-26
Nun muss ich die Differenz zwischen diesen beiden in der folgenden Form finden:
2 years, 3 months and 2 days
Wie kann ich dies in PHP tun?
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 ";
mehr lesen php DateTime::diff manuell
Aus dem Handbuch:
Seit 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)
+1 DateTime geht mit Schaltjahren und Zeitzonen richtig um und es gibt ein gutes Buch für das Regal: phparch.com/books/
Gibt es eine Methode, die die Gesamtzahl der Sekunden zwischen den beiden DateTimes gibt? (ohne die Komponenten zu addieren, das heißt)
Korrigieren Sie mich, wenn ich falsch liege, aber ich denke, es muss sein $interval->days
代わりに $interval->d
!?!?!?
Verwenden Sie dies für älteren Code (PHP < 5.3). Für eine aktuelle Lösung siehe die Antwort von Jurka unten
Sie können strtotime() verwenden, um zwei Datumsangaben in Unix-Zeit umzuwandeln und dann die Anzahl der Sekunden zwischen ihnen zu berechnen. Daraus lassen sich recht einfach verschiedene Zeiträume 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);
Editar: Die bevorzugte Vorgehensweise ist natürlich die von jurka beschriebene. Mein Code wird im Allgemeinen nur empfohlen, wenn Sie nicht über PHP 5.3 oder besser verfügen.
Mehrere Personen haben in den Kommentaren darauf hingewiesen, dass der obige Code nur ein Näherungswert ist. Ich bin nach wie vor der Meinung, dass das 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, und nicht dazu, Präzision zu bieten - wenn Sie das tun wollen, geben Sie einfach das Datum aus.
Trotz alledem habe ich beschlossen, auf die Beschwerden einzugehen. Wenn Sie wirklich einen exakten Bereich benötigen, aber keinen Zugang zu PHP 5.3 haben, verwenden Sie den folgenden Code (er sollte auch in PHP 4 funktionieren). Dies ist eine direkte Portierung des Codes, den PHP intern zur Berechnung von Zeiträumen verwendet, mit der Ausnahme, dass er die Sommerzeit nicht berücksichtigt. Das bedeutet, dass er höchstens um eine Stunde daneben liegt, aber ansonsten sollte er 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)));
Wenn Sie die DateTime-Klasse verwenden, können Sie $date->format('U') verwenden, um den Unix-Zeitstempel zu erhalten.
Das stimmt nicht, wenn man sich mit der Sommer-/Winterzeit befassen muss. In diesem speziellen Fall, wenn man die Sommer-/Winterzeit umstellt, entspricht ein Tag 23 oder 25 Stunden.
Nun, dasselbe Argument könnte man auch für Schaltjahre anführen. Auch das wird nicht berücksichtigt. Ich bin jedoch nicht davon überzeugt, dass Sie das überhaupt berücksichtigen wollen, da wir hier über eine Spanne sprechen. Die Semantik für eine Spanne ist etwas anders als für ein absolutes Datum.
Die beste Vorgehensweise ist die Verwendung der PHP-Funktion DateTime
(und DateInterval
) Objekte. Jedes Datum ist gekapselt in einem DateTime
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");
El DateTime
Objekt wird jedes Format akzeptieren strtotime()
würde. Wenn ein noch genaueres Datumsformat benötigt wird, DateTime::createFromFormat()
kann verwendet werden, um die DateTime
Objekt.
Nachdem beide Objekte instanziiert wurden, subtrahieren Sie das eine vom anderen mit DateTime::diff()
.
$difference = $first_date->diff($second_date);
$difference
hält nun eine DateInterval
Objekt 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
Zum Formatieren der DateInterval
Objekts müssen wir jeden Wert überprüfen und ihn 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 in der Datei $difference
DateInterval
Objekt:
echo format_interval($difference);
Und wir erhalten das richtige Ergebnis:
20 Tage 6 Stunden 56 Minuten 30 Sekunden
Der vollständige Code, der zur Erreichung des Ziels verwendet wird:
/**
* 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);
DateTime()
ist keine Funktion, sondern ein Objekt, und es gibt sie seit PHP 5.2. Stellen Sie sicher, dass Ihr Server es unterstützt.
Wir haben ein Problem: Wir tauschen das erste Datum gegen das zweite Datum aus und erhalten dasselbe Ergebnis? Warum nicht sagen 0 Tage 0 Stunden 0 Minuten 0 Sekunden oder nur 0. 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.
Ansicht Stunden und Minuten und Sekunden..
$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);
Und ist eine schreckliche Lösung, es sei denn, Sie sind gezwungen, eine schrecklich veraltete Version von PHP zu verwenden ...
Nicht so DRY . Zum Beispiel wird 60*60*24 15 Mal wiederholt. Es lebe die Wiederverwendung von Kopieren und Einfügen!
Werfen Sie einen Blick auf den folgenden Link. Das ist die beste Antwort, die ich bis jetzt 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 ist, wenn Sie in der Datumsparameter übergeben. Die Funktion verwendet den PHP ABS()-Absolutwert, um immer eine positive Zahl als die Anzahl der Tage zwischen den beiden Daten zurück Daten.
Beachten Sie, dass die Anzahl der Tage zwischen den beiden Daten NICHT beide Daten umfasst. Wenn Sie also nach der Anzahl der Tage suchen die durch alle Daten zwischen den eingegebenen Daten repräsentiert werden, müssen Sie zum Ergebnis dieser Funktion eine (1) addieren.
Die Differenz (die von der obigen Funktion zurückgegeben wird) ist zum Beispiel zwischen 2013-02-09 und 2013-02-14 ist 5. Aber die Anzahl der Tage oder Daten, die durch den Datumsbereich 2013-02-09 - 2013-02-14 repräsentiert werden, ist 6.
CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.
3 Stimmen
2 Jahre 94 Tage. Die Berechnung der Monate unter Berücksichtigung der Schaltjahre wäre problematisch. Wie genau muss dies sein?
0 Stimmen
Mögliche Duplikate von Wie kann ich die relative Zeit berechnen?