Tôi có hai ngày của mẫu:
Start Date: 2007-03-24
End Date: 2009-06-26
Bây giờ tôi cần tìm sự khác biệt giữa hai cái này theo mẫu sau:
2 years, 3 months and 2 days
Làm thế nào tôi có thể làm điều này trong PHP?
Tôi có hai ngày của mẫu:
Start Date: 2007-03-24
End Date: 2009-06-26
Bây giờ tôi cần tìm sự khác biệt giữa hai cái này theo mẫu sau:
2 years, 3 months and 2 days
Làm thế nào tôi có thể làm điều này trong PHP?
Câu trả lời:
Sử dụng mã này cho mã kế thừa (PHP <5.3). Để biết giải pháp cập nhật, hãy xem câu trả lời của Jurka bên dưới
Bạn có thể sử dụng strtotime () để chuyển đổi hai ngày thành thời gian unix và sau đó tính số giây giữa chúng. Từ đó, việc tính toán các khoảng thời gian khác nhau khá dễ dàng.
$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);
Chỉnh sửa: Rõ ràng cách thức ưa thích để làm điều này giống như được mô tả bởi Jurka dưới đây. Mã của tôi thường chỉ được khuyến nghị nếu bạn không có PHP 5.3 trở lên.
Một số người trong các ý kiến đã chỉ ra rằng mã ở trên chỉ là một xấp xỉ. Tôi vẫn tin rằng đối với hầu hết các mục đích đều ổn, vì việc sử dụng phạm vi nhiều hơn để mang lại cảm giác thời gian đã trôi qua hoặc vẫn còn hơn là để cung cấp độ chính xác - nếu bạn muốn làm điều đó, chỉ cần xuất ngày.
Mặc dù vậy, tôi đã quyết định giải quyết các khiếu nại. Nếu bạn thực sự cần một phạm vi chính xác nhưng chưa có quyền truy cập vào PHP 5.3, hãy sử dụng mã bên dưới (nó cũng hoạt động trong PHP 4). Đây là một cổng trực tiếp của mã mà PHP sử dụng nội bộ để tính toán phạm vi, ngoại trừ việc nó không mất thời gian tiết kiệm ánh sáng ban ngày. Điều đó có nghĩa là tối đa là một giờ, nhưng ngoại trừ điều đó là chính xác.
<?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)));
&
để chữ ký.
Tôi đề nghị sử dụng các đối tượng DateTime và 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 ";
đọc thêm php DateTime :: hướng dẫn sử dụng khác
Từ hướng dẫn:
Kể từ PHP 5.2.2, các đối tượng DateTime có thể được so sánh bằng các toán tử so sánh.
$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')
.
Khóa học hành động tốt nhất là sử dụng các đối tượng DateTime
(và DateInterval
) của PHP . Mỗi ngày được gói gọn trong một DateTime
đối tượng và sau đó có thể tạo ra sự khác biệt giữa hai ngày:
$first_date = new DateTime("2012-11-30 17:03:30");
$second_date = new DateTime("2012-12-21 00:00:00");
Đối DateTime
tượng sẽ chấp nhận bất kỳ định dạng strtotime()
nào. Nếu cần một định dạng ngày cụ thể hơn nữa, DateTime::createFromFormat()
có thể được sử dụng để tạo DateTime
đối tượng.
Sau khi cả hai đối tượng được khởi tạo, bạn trừ đi một đối tượng khác DateTime::diff()
.
$difference = $first_date->diff($second_date);
$difference
bây giờ giữ một DateInterval
đối tượng với thông tin khác biệt. Một var_dump()
hình như thế này:
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
Để định dạng DateInterval
đối tượng, chúng tôi sẽ cần kiểm tra từng giá trị và loại trừ nó nếu nó là 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;
}
Tất cả những gì còn lại bây giờ là gọi hàm của chúng ta trên $difference
DateInterval
đối tượng:
echo format_interval($difference);
Và chúng tôi nhận được kết quả chính xác:
20 ngày 6 giờ 56 phút 30 giây
Mã hoàn chỉnh được sử dụng để đạt được mục tiêu:
/**
* 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()
không phải là một hàm, nó là một đối tượng và nó ở đó kể từ PHP 5.2. Hãy chắc chắn rằng máy chủ của bạn hỗ trợ nó.
Xem giờ và phút và giây ..
$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);
Hãy xem liên kết sau đây. Đây là câu trả lời tốt nhất mà tôi đã tìm thấy cho đến nay .. :)
function dateDiff ($d1, $d2) {
// Return the number of days between the two dates:
return round(abs(strtotime($d1) - strtotime($d2))/86400);
} // end function dateDiff
Không quan trọng ngày nào sớm hơn hay muộn hơn khi bạn chuyển các tham số ngày. Hàm sử dụng giá trị tuyệt đối của PHP ABS () để luôn trả về số thứ tự là số ngày giữa hai ngày.
Hãy nhớ rằng số ngày giữa hai ngày KHÔNG bao gồm cả hai ngày. Vì vậy, nếu bạn đang tìm kiếm số ngày được biểu thị bằng tất cả các ngày giữa và kể cả ngày đã nhập, bạn sẽ cần thêm một (1) vào kết quả của hàm này.
Ví dụ: sự khác biệt (như được trả về bởi chức năng trên) giữa 2013 / 02-09 và 2013/02/14 là 5. Nhưng số ngày hoặc ngày được biểu thị bằng phạm vi ngày 2013 / 02-09 - 2013 / 02- 14 là 6.
Tôi đã bình chọn cho câu trả lời của Jurka là câu hỏi yêu thích của tôi, nhưng tôi có phiên bản tiền php.5.3 ...
Tôi thấy mình đang giải quyết một vấn đề tương tự - đó là cách tôi có được câu hỏi này ngay từ đầu - nhưng chỉ cần một sự khác biệt về giờ. Nhưng chức năng của tôi cũng đã giải quyết vấn đề này khá tốt và tôi không có nơi nào trong thư viện của riêng mình để giữ nó ở nơi nó sẽ không bị mất và bị lãng quên, vì vậy ... hy vọng điều này hữu ích với ai đó.
/**
*
* @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;
}
Và bài kiểm tra:
$oDate = new DateTime();
$oDate->modify('+111402189 seconds');
var_dump($oDate);
var_dump(date_diff_array(new DateTime(), $oDate));
Và kết quả:
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
Tôi đã có ý tưởng ban đầu từ đây , mà tôi đã sửa đổi cho mục đích sử dụng của mình (và tôi hy vọng sửa đổi của mình cũng sẽ hiển thị trên trang đó).
Bạn có thể dễ dàng loại bỏ các khoảng thời gian bạn không muốn (nói "tuần") bằng cách xóa chúng khỏi $aIntervals
mảng hoặc có thể thêm một $aExclude
tham số hoặc chỉ lọc chúng khi bạn xuất chuỗi.
week
chỉ mục trong $aIntervals
(vì DateDiff
không bao giờ sử dụng điều đó).
<?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);
?>
Tôi không biết bạn có đang sử dụng khung PHP hay không, nhưng rất nhiều khung PHP có thư viện ngày / giờ và người trợ giúp để giúp bạn không phát minh lại bánh xe.
Ví dụ CodeIgniter có timespan()
chức năng. Chỉ cần nhập hai dấu thời gian Unix và nó sẽ tự động tạo ra kết quả như thế này:
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';
}
Tôi có một số logic đơn giản cho điều đó:
<?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;
?>
Bạn có thể dùng
getdate()
Hàm trả về một mảng chứa tất cả các phần tử của ngày / thời gian được cung cấp:
$diff = abs($endDate - $startDate);
$my_t=getdate($diff);
print("$my_t[year] years, $my_t[month] months and $my_t[mday] days");
Nếu ngày bắt đầu và ngày kết thúc của bạn ở định dạng chuỗi thì hãy sử dụng
$startDate = strtotime($startDateStr);
$endDate = strtotime($endDateStr);
trước đoạn mã trên
$my_t["year"] -= 1970
để có được số năm chính xác. Bạn cũng cần phải trừ đi chênh lệch giờ của bạn từ GMT để có được số giờ đúng. Bạn cần phải trừ 1 từ tháng và ngày.
// 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;
}
Đây là chức năng của tôi. Yêu cầu PHP> = 5.3.4. Nó sử dụng lớp DateTime. Rất nhanh, nhanh và có thể tạo ra sự khác biệt giữa hai ngày hoặc thậm chí còn gọi là "thời gian kể từ khi".
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;
}
}
Tôi muốn sử dụng date_create
và date_diff
các đối tượng.
Mã số:
$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;
Đầu ra:
2 years, 3 months and 2 days
Để biết thêm thông tin đọc hướng dẫn sử dụng PHPdate_diff
Theo hướng dẫn
date_diff
là một bí danh của DateTime :: diff ()
Điều này sẽ cố gắng phát hiện xem dấu thời gian có được đưa ra hay không và cũng sẽ trả về ngày / lần trong tương lai dưới dạng giá trị âm:
<?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;
}
Ví dụ sử dụng:
<?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
Hoặc là:
<?php
$christmas_2020 = 'December 25, 2020';
$countdown = time_diff($christmas_2020);
print_r($countdown);
"nếu" ngày được lưu trữ trong MySQL, tôi thấy việc tính toán chênh lệch ở cấp cơ sở dữ liệu dễ dàng hơn ... Sau đó, dựa trên kết quả Ngày, Giờ, Tối thiểu, Giây, phân tích và hiển thị kết quả phù hợp ...
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)
Tôi tìm thấy bài viết của bạn trên trang sau, trong đó có một số tài liệu tham khảo cho các tính toán thời gian ngày của PHP .
Tính toán sự khác biệt giữa hai Ngày (và thời gian) bằng PHP. Trang sau cung cấp một loạt các phương pháp khác nhau (tổng cộng 7) để thực hiện tính toán ngày / giờ bằng PHP, để xác định sự khác biệt về thời gian (giờ, munites), ngày, tháng hoặc năm giữa hai ngày.
Xem Thời gian ngày của PHP - 7 phương pháp để tính toán sự khác biệt giữa 2 ngày .
Bạn cũng có thể sử dụng mã sau để trả về ngày khác bằng cách phân số tròn lên $ date1 = $ duedate; // gán ngày đáo hạn echo $ date2 = date ("Ymd"); // ngày hiện tại $ ts1 = strtotime ($ date1); $ ts2 = strtotime ($ date2); $ giây_diff = $ ts1 - $ ts2; echo $ dateiff = ceil (($ giây_diff / 3600) / 24); // trở lại sau vài ngày
Nếu bạn sử dụng phương thức sàn của php thay vì trần, nó sẽ trả về cho bạn phần tròn. Vui lòng kiểm tra sự khác biệt ở đây, đôi khi nếu múi giờ của máy chủ dàn của bạn khác thì múi giờ của trang trực tiếp trong trường hợp đó bạn có thể nhận được kết quả khác nhau để thay đổi điều kiện cho phù hợp.
bạn luôn có thể sử dụng chức năng sau có thể trả về tuổi theo năm và tháng (tức là 1 năm 4 tháng)
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;
}
hoặc nếu bạn muốn tính tuổi ở ngày hiện tại, bạn có thể sử dụng
function getAge($dob)
{
$d1 = new DateTime($dob);
$d2 = new DateTime(date());
$age = $d2->diff($d1);
$years = $age->y;
$months = $age->m;
return $years.'.'.months;
}
Đối với phiên bản php> = 5.3: Tạo hai đối tượng ngày và sau đó sử dụng date_diff()
hàm. Nó sẽ trả về đối tượng php DateInterval . xem tài liệu
$date1=date_create("2007-03-24");
$date2=date_create("2009-06-26");
$diff=date_diff($date1,$date2);
echo $diff->format("%R%a days");
Tôi đã có cùng một vấn đề với PHP 5.2 và đã giải quyết nó với MySQL. Có thể không chính xác những gì bạn đang tìm kiếm, nhưng điều này sẽ thực hiện thủ thuật và trả về số ngày:
$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;
Thêm thông tin tại đây http://dev.mysql.com/doc/refman/5.5/en/date-and-time-fifts.html#feft_datediff
Vì tất cả mọi người đang đăng mẫu mã, đây là một phiên bản khác.
Tôi muốn một chức năng để hiển thị sự khác biệt từ vài giây đến nhiều năm (chỉ một đơn vị). Trong khoảng thời gian hơn 1 ngày, tôi muốn nó quay vòng vào nửa đêm (10 giờ sáng thứ Hai được nhìn thấy từ 9 giờ sáng thứ Tư là 2 ngày trước, không phải 1). Và trong khoảng thời gian hơn một tháng, tôi muốn tái đầu tư vào cùng một ngày trong tháng (bao gồm 30,31 tháng ngày và năm nhuận).
Đây là những gì tôi nghĩ ra:
/**
* 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';
}
Cách đây một thời gian tôi đã viết một format_date
chức năng vì điều này cung cấp nhiều tùy chọn về cách bạn muốn ngày của bạn :
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);
}
Rất đơn giản:
<?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>";
?>
Vui lòng kiểm tra liên kết sau để biết chi tiết:
Lưu ý rằng đó là phiên bản PHP 5.3.0 trở lên.
Một chức năng dễ dàng
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);
}
Sử dụng như
echo time_difference ($time_1, $time_2, "day");
Sẽ trở lại như thế nào 2 years 8 months 2 days
Hãy thử câu trả lời rất đơn giản này bằng date_diff () , điều này đã được kiểm tra.
$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;
đầu ra là:
1 years 1 months 2 days
Tôi đang sử dụng hàm sau mà tôi đã viết, khi PHP 5.3 (tương ứng date_diff ()) không khả dụng:
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
là tuyệt vời nhưng nó có một vài cảnh báo:
Để khắc phục điều đó, tôi đã mã hóa như sau (được cải thiện từ câu trả lời @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;
}
Nó chạy hai vòng; cái thứ nhất liên quan đến các khoảng tương đối (năm và tháng) thông qua cưỡng bức, và cái thứ hai tính các khoảng tuyệt đối bổ sung với số học đơn giản (vì vậy nhanh hơn):
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);
}