Mam dwie daty formularza:
Start Date: 2007-03-24
End Date: 2009-06-26
Teraz muszę znaleźć różnicę między tymi dwoma w następującej formie:
2 years, 3 months and 2 days
Jak mogę to zrobić w PHP?
Mam dwie daty formularza:
Start Date: 2007-03-24
End Date: 2009-06-26
Teraz muszę znaleźć różnicę między tymi dwoma w następującej formie:
2 years, 3 months and 2 days
Jak mogę to zrobić w PHP?
Odpowiedzi:
Użyj tego dla starszego kodu (PHP <5.3). Aktualne rozwiązanie znajduje się w odpowiedzi jurki poniżej
Możesz użyć strtotime (), aby przekonwertować dwie daty na czas uniksowy, a następnie obliczyć liczbę sekund między nimi. Na tej podstawie łatwo jest obliczyć różne okresy.
$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);
Edycja: Oczywiście preferowanym sposobem na zrobienie tego jest opisany poniżej przez jurka. Mój kod jest ogólnie zalecany tylko wtedy, gdy nie masz PHP 5.3 lub nowszego.
Kilka osób w komentarzach zauważyło, że powyższy kod jest jedynie przybliżeniem. Nadal uważam, że dla większości celów jest to w porządku, ponieważ użycie zakresu służy raczej do określenia, ile czasu minęło lub pozostało, niż do zapewnienia precyzji - jeśli chcesz to zrobić, po prostu podaj datę.
Mimo to postanowiłem zająć się skargami. Jeśli naprawdę potrzebujesz dokładnego zakresu, ale nie masz dostępu do PHP 5.3, użyj poniższego kodu (powinien również działać w PHP 4). Jest to bezpośredni port kodu, którego PHP używa wewnętrznie do obliczania zakresów, z tym wyjątkiem, że nie bierze pod uwagę czasu letniego. Oznacza to, że jest wyłączony najwyżej o godzinę, ale poza tym powinien być poprawny.
<?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)));
&
do podpisów.
Sugeruję użycie obiektów DateTime i DateInterval.
$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 ";
czytaj więcej php DateTime :: diff manual
Z instrukcji:
Począwszy od PHP 5.2.2, obiekty DateTime można porównywać za pomocą operatorów porównania.
$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)
$date2->format('U') - $date1->format('U')
.
Najlepszym sposobem działania jest użycie obiektów PHP DateTime
(i DateInterval
). Każda data jest kapsułkowana w DateTime
obiekcie, a następnie można wprowadzić różnicę między nimi:
$first_date = new DateTime("2012-11-30 17:03:30");
$second_date = new DateTime("2012-12-21 00:00:00");
DateTime
Obiekt zaakceptuje każdy format strtotime()
będzie. Jeśli potrzebny jest jeszcze bardziej szczegółowy format daty, DateTime::createFromFormat()
można go użyć do utworzenia DateTime
obiektu.
Po utworzeniu instancji obu obiektów odejmujesz jeden od drugiego za pomocą DateTime::diff()
.
$difference = $first_date->diff($second_date);
$difference
teraz zawiera DateInterval
obiekt z informacją o różnicy. A var_dump()
wygląda to tak:
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
Aby sformatować DateInterval
obiekt, musimy sprawdzić każdą wartość i wykluczyć ją, jeśli wynosi 0:
/**
* 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;
}
Teraz pozostaje tylko wywołać naszą funkcję na $difference
DateInterval
obiekcie:
echo format_interval($difference);
I otrzymujemy poprawny wynik:
20 dni 6 godzin 56 minut 30 sekund
Pełny kod użyty do osiągnięcia celu:
/**
* 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()
nie jest funkcją, jest obiektem i istnieje od PHP 5.2. Upewnij się, że Twój serwer to obsługuje.
Zobacz godziny, minuty i sekundy ..
$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);
Spójrz na poniższy link. To najlepsza odpowiedź, jaką do tej pory znalazłem .. :)
function dateDiff ($d1, $d2) {
// Return the number of days between the two dates:
return round(abs(strtotime($d1) - strtotime($d2))/86400);
} // end function dateDiff
Nie ma znaczenia, która data jest wcześniejsza czy późniejsza, gdy podasz parametry daty. Funkcja wykorzystuje wartość bezwzględną ABS () PHP, aby zawsze zwracać liczbę dodatnią jako liczbę dni między dwiema datami.
Pamiętaj, że liczba dni między dwiema datami NIE obejmuje obu dat. Jeśli więc szukasz liczby dni reprezentowanych przez wszystkie daty między wprowadzonymi datami włącznie, musisz dodać jeden (1) do wyniku tej funkcji.
Na przykład różnica (zwrócona przez powyższą funkcję) między 2013-02-09 a 2013-02-14 wynosi 5. Ale liczba dni lub dat reprezentowana przez zakres dat 2013-02-09 - 2013-02- 14 to 6.
Głosowałem za Jurka „s odpowiedź jak to mój ulubiony, ale mam wersję pre-php.5.3 ...
Odkryłem, że pracuję nad podobnym problemem - w ten sposób przede wszystkim dotarłem do tego pytania - ale potrzebowałem tylko różnicy godzin. Ale moja funkcja rozwiązała to całkiem nieźle i nie mam nigdzie w mojej własnej bibliotece, aby przechowywać ją tam, gdzie nie zostanie zgubiona i zapomniana, więc ... mam nadzieję, że jest to przydatne dla kogoś.
/**
*
* @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;
}
I test:
$oDate = new DateTime();
$oDate->modify('+111402189 seconds');
var_dump($oDate);
var_dump(date_diff_array(new DateTime(), $oDate));
A wynik:
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
Stąd otrzymałem oryginalny pomysł , który zmodyfikowałem dla moich zastosowań (i mam nadzieję, że moja modyfikacja pojawi się również na tej stronie).
Możesz bardzo łatwo usunąć interwały, których nie chcesz (powiedz „tydzień”), usuwając je z $aIntervals
tablicy lub dodając $aExclude
parametr, lub po prostu odfiltrowując je, gdy wypisujesz ciąg.
week
indeks w $aIntervals
(ponieważ DateDiff
nigdy tego nie używa).
<?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);
?>
Nie wiem, czy używasz frameworka PHP, czy nie, ale wiele frameworków PHP ma biblioteki daty / godziny i pomocniki, które pomogą Ci powstrzymać się od ponownego wynalezienia koła.
Na przykład CodeIgniter ma timespan()
funkcję. Po prostu wprowadź dwa znaczniki czasu Unix, a automatycznie wygeneruje taki wynik:
1 Year, 10 Months, 2 Weeks, 5 Days, 10 Hours, 16 Minutes
echo time_diff_string('2013-05-01 00:22:35', 'now');
echo time_diff_string('2013-05-01 00:22:35', 'now', true);
4 months ago
4 months, 2 weeks, 3 days, 1 hour, 49 minutes, 15 seconds ago
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';
}
Mam do tego prostą logikę:
<?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;
?>
Możesz użyć
getdate()
funkcja, która zwraca tablicę zawierającą wszystkie elementy podanej daty / godziny:
$diff = abs($endDate - $startDate);
$my_t=getdate($diff);
print("$my_t[year] years, $my_t[month] months and $my_t[mday] days");
Jeśli data początkowa i końcowa mają format ciągów, użyj
$startDate = strtotime($startDateStr);
$endDate = strtotime($endDateStr);
przed powyższym kodem
$my_t["year"] -= 1970
aby uzyskać prawidłową liczbę lat. Należy również odjąć swój różnicę godziny od GMT, aby uzyskać prawo godzin. Musisz również odjąć 1 od miesiąca i daty.
// 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;
}
To moja funkcja. Wymagane PHP> = 5.3.4. Używa klasy DateTime. Bardzo szybko, szybko i może zrobić różnicę między dwiema datami, a nawet tak zwanym „czasem od”.
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;
}
}
Wolałbym używać date_create
i date_diff
obiektów.
Kod:
$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;
Wynik:
2 years, 3 months and 2 days
Aby uzyskać więcej informacji, przeczytaj instrukcję PHPdate_diff
Zgodnie z instrukcją
date_diff
jest pseudonimem DateTime :: diff ()
Spróbuje to wykryć, czy podany został znacznik czasu, a także zwróci przyszłe daty / godziny jako wartości ujemne:
<?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;
}
Przykładowe użycie:
<?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
Lub:
<?php
$christmas_2020 = 'December 25, 2020';
$countdown = time_diff($christmas_2020);
print_r($countdown);
„jeśli” data jest przechowywana w MySQL, łatwiej jest mi wykonać obliczenie różnicy na poziomie bazy danych ... Następnie na podstawie danych wyjściowych Dzień, Godzina, Min, Sek, parsowanie i wyświetlanie wyników odpowiednio ...
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)
Znalazłem twój artykuł na następnej stronie, która zawiera szereg odniesień do obliczeń daty i godziny w PHP .
Oblicz różnicę między dwiema datami (i czasem) za pomocą PHP. Następująca strona zawiera szereg różnych metod (łącznie 7) do wykonywania obliczeń daty / godziny za pomocą PHP, w celu ustalenia różnicy czasu (godziny, munity), dni, miesięcy lub lat między dwiema datami.
Zobacz PHP Data Godzina - 7 metod obliczania różnicy między 2 datami .
Możesz także użyć następującego kodu, aby zwrócić różnicę daty o ułamki zaokrąglone w górę $ date1 = $ duedate; // przypisanie terminu echo $ date2 = data („Ymd”); // bieżąca data $ ts1 = strtotime ($ date1); $ ts2 = strtotime ($ date2); $ seconds_diff = $ ts1 - $ ts2; echo $ datediff = ceil (($ seconds_diff / 3600) / 24); // powrót za kilka dni
Jeśli użyjesz metody podłogowej php zamiast sufitu, zwróci ci ona okrągłą frakcję w dół. Sprawdź różnicę tutaj, czasami, jeśli strefa czasowa serwerów pomostowych jest inna niż strefa czasowa witryny na żywo, w takim przypadku możesz uzyskać inne wyniki, więc odpowiednio zmień warunki.
zawsze możesz skorzystać z następującej funkcji, która może przywrócić wiek w latach i miesiącach (tj. 1 rok 4 miesiące)
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;
}
lub jeśli chcesz, aby wiek był obliczany na bieżącą datę, możesz użyć
function getAge($dob)
{
$d1 = new DateTime($dob);
$d2 = new DateTime(date());
$age = $d2->diff($d1);
$years = $age->y;
$months = $age->m;
return $years.'.'.months;
}
Dla wersji php> = 5.3: Utwórz dwa obiekty daty, a następnie użyj date_diff()
funkcji. Zwróci obiekt DateInterval php . patrz dokumentacja
$date1=date_create("2007-03-24");
$date2=date_create("2009-06-26");
$diff=date_diff($date1,$date2);
echo $diff->format("%R%a days");
Miałem ten sam problem z PHP 5.2 i rozwiązałem go za pomocą MySQL. Może nie być dokładnie tym, czego szukasz, ale to załatwi sprawę i zwróci liczbę dni:
$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;
Więcej informacji tutaj http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html#function_datediff
Ponieważ wszyscy publikują próbki kodu, oto inna wersja.
Chciałem, aby funkcja wyświetlała różnice od sekund do lat (tylko jedna jednostka). W przypadku okresów dłuższych niż 1 dzień chciałem, aby kumulował się o północy (10 rano w poniedziałek widziany od 9 rano w środę jest 2 dni temu, a nie 1). I dla okresów powyżej miesiąca chciałem, aby rolowanie miało miejsce tego samego dnia miesiąca (w tym dla miesięcy 30 i 31 dni przestępnych).
Oto co wymyśliłem:
/**
* 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';
}
Jakiś czas temu napisałem format_date
funkcję, ponieważ daje wiele opcji, w jaki sposób chcesz mieć swoją datę :
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);
}
Bardzo prosta:
<?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>";
?>
Proszę sprawdzić poniższy link, aby uzyskać szczegółowe informacje:
Zauważ, że dotyczy PHP 5.3.0 lub nowszego.
Łatwa funkcja
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);
}
Użyj jak
echo time_difference ($time_1, $time_2, "day");
Wróci jak 2 years 8 months 2 days
Wypróbuj tę bardzo prostą odpowiedź za pomocą date_diff () , to jest przetestowane.
$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;
dane wyjściowe to:
1 years 1 months 2 days
Korzystam z następującej funkcji, którą napisałem, gdy PHP 5.3 (odpowiednio date_diff ()) nie jest dostępne:
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);
}
DateInterval
jest świetne, ale ma kilka zastrzeżeń:
Aby temu zaradzić, napisałem następujące (poprawione z odpowiedzi @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;
}
Działa dwie pętle; pierwszy dotyczy względnych przedziałów (lat i miesięcy) za pomocą brutalnego wymuszania, a drugi oblicza dodatkowe przedziały bezwzględne za pomocą prostej arytmetyki (więc jest szybszy):
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);
}