计算两个日期之间的天数

如何使用PHP查找两个日期之间的天数?

1071171 次浏览

如果你的时间以秒为单位(即unix时间戳),那么你可以简单地减去时间并除以86400(每天秒)

将您的日期转换为unix时间戳,然后将一个日期与另一个日期相减。这将为您提供秒的差异,您可以将其除以86400(一天中的秒数),从而获得该范围内的大致天数。

如果您的日期格式为25.1.201001/25/20102010-01-25,则可以使用strtotime函数:

$start = strtotime('2010-01-25');
$end = strtotime('2010-02-20');


$days_between = ceil(abs($end - $start) / 86400);

使用ceil将天数舍入到下一个完整日。如果您想获取这两个日期之间的完整天数,请改用floor

如果您的日期已经是unix时间戳格式,您可以跳过转换并只执行$days_between部分。对于更奇特的日期格式,您可能需要进行一些自定义解析才能正确。

$now = time(); // or your date as well
$your_date = strtotime("2010-01-31");
$datediff = $now - $your_date;


echo round($datediff / (60 * 60 * 24));

使用这个:)

$days = (strtotime($endDate) - strtotime($startDate)) / (60 * 60 * 24);
print $days;

现在起作用了

$datediff = floor(strtotime($date1)/(60*60*24)) - floor(strtotime($date2)/(60*60*24));

如果需要的话:

$datediff=abs($datediff);
    // Change this to the day in the future
$day = 15;


// Change this to the month in the future
$month = 11;


// Change this to the year in the future
$year = 2012;


// $days is the number of days between now and the date in the future
$days = (int)((mktime (0,0,0,$month,$day,$year) - time(void))/86400);


echo "There are $days days until $day/$month/$year";

如果您使用的是PHP 5.3 >,这是迄今为止计算绝对差异的最准确方法:

$earlier = new DateTime("2010-07-06");
$later = new DateTime("2010-07-09");


$abs_diff = $later->diff($earlier)->format("%a"); //3

如果您需要相对(签名)天数,请改用:

$earlier = new DateTime("2010-07-06");
$later = new DateTime("2010-07-09");


$pos_diff = $earlier->diff($later)->format("%r%a"); //3
$neg_diff = $later->diff($earlier)->format("%r%a"); //-3

更多关于php的DateInterval格式可以在这里找到:https://www.php.net/manual/en/dateinterval.format.php

function howManyDays($startDate,$endDate) {


$date1  = strtotime($startDate." 0:00:00");
$date2  = strtotime($endDate." 23:59:59");
$res    =  (int)(($date2-$date1)/86400);


return $res;
}
$start = '2013-09-08';
$end = '2013-09-15';
$diff = (strtotime($end)- strtotime($start))/24/3600;
echo $diff;

如果你想在开始日期和结束日期之间回声所有日子,我想出了这个:

$startdatum = $_POST['start']; // starting date
$einddatum = $_POST['eind']; // end date


$now = strtotime($startdatum);
$your_date = strtotime($einddatum);
$datediff = $your_date - $now;
$number = floor($datediff/(60*60*24));


for($i=0;$i <= $number; $i++)
{
echo date('d-m-Y' ,strtotime("+".$i." day"))."<br>";
}

易于使用date_diff

$from=date_create(date('Y-m-d'));
$to=date_create("2013-03-15");
$diff=date_diff($to,$from);
print_r($diff);
echo $diff->format('%R%a days');

从PHP版本5.3及更高版本开始,添加了新的日期/时间功能以获得差异:

$datetime1 = new DateTime("2010-06-20");


$datetime2 = new DateTime("2011-06-22");


$difference = $datetime1->diff($datetime2);


echo 'Difference: '.$difference->y.' years, '
.$difference->m.' months, '
.$difference->d.' days';


print_r($difference);

结果如下:

Difference: 1 years, 0 months, 2 days


DateInterval Object
(
[y] => 1
[m] => 0
[d] => 2
[h] => 0
[i] => 0
[s] => 0
[invert] => 0
[days] => 367
)

希望有帮助!

如果你使用MySQL

function daysSince($date, $date2){
$q = "SELECT DATEDIFF('$date','$date2') AS days;";
$result = execQ($q);
$row = mysql_fetch_array($result,MYSQL_BOTH);
return ($row[0]);

}

function execQ($q){
$result = mysql_query( $q);
if(!$result){echo ('Database error execQ' . mysql_error());echo $q;}
return $result;

}

我在我的作曲家项目中使用用于这个和类似的目的。

就像这样简单:

$dt = Carbon::parse('2010-01-01');
echo $dt->diffInDays(Carbon::now());

面向对象的风格:

$datetime1 = new DateTime('2009-10-11');
$datetime2 = new DateTime('2009-10-13');
$interval = $datetime1->diff($datetime2);
echo $interval->format('%R%a days');

程序风格:

$datetime1 = date_create('2009-10-11');
$datetime2 = date_create('2009-10-13');
$interval = date_diff($datetime1, $datetime2);
echo $interval->format('%R%a days');

这是我的改进版本,如果传递了第二个参数,则显示1年2个月25天。

class App_Sandbox_String_Util {
/**
* Usage: App_Sandbox_String_Util::getDateDiff();
* @param int $your_date timestamp
* @param bool $hr human readable. e.g. 1 year(s) 2 day(s)
* @see http://stackoverflow.com/questions/2040560/finding-the-number-of-days-between-two-dates
* @see http://qSandbox.com
*/
static public function getDateDiff($your_date, $hr = 0) {
$now = time(); // or your date as well
$datediff = $now - $your_date;
$days = floor( $datediff / ( 3600 * 24 ) );


$label = '';


if ($hr) {
if ($days >= 365) { // over a year
$years = floor($days / 365);
$label .= $years . ' Year(s)';
$days -= 365 * $years;
}


if ($days) {
$months = floor( $days / 30 );
$label .= ' ' . $months . ' Month(s)';
$days -= 30 * $months;
}


if ($days) {
$label .= ' ' . $days . ' day(s)';
}
} else {
$label = $days;
}


return $label;
}
}

尝试使用Carbon

$d1 = \Carbon\Carbon::now()->subDays(92);
$d2 = \Carbon\Carbon::now()->subDays(10);
$days_btw = $d1->diffInDays($d2);

您也可以使用

\Carbon\Carbon::parse('')

使用给定的时间戳字符串创建Carbon date对象。

太长别读 do没有使用UNIX时间戳。不要使用time()。如果你这样做,准备应该其98.0825%的可靠性让你失望。使用日期时间(或碳)。

正确答案是Saksham Gupta给出的答案(其他答案也正确):

$date1 = new DateTime('2010-07-06');
$date2 = new DateTime('2010-07-09');
$days  = $date2->diff($date1)->format('%a');

或者在程序上作为一个单行:

/**
* Number of days between two dates.
*
* @param date $dt1    First date
* @param date $dt2    Second date
* @return int
*/
function daysBetween($dt1, $dt2) {
return date_diff(
date_create($dt2),
date_create($dt1)
)->format('%a');
}

注意:'%a'似乎表示绝对天数。如果您想将其作为有符号整数,即当第二个日期在第一个日期之前时为负,那么您需要使用'%r'前缀(即format('%r%a'))。


如果你真的必须使用UNIX时间戳,将时区设置为GMT可以避免大多数下面详述的陷阱。


长答案:为什么除以24*60*60(又名86400)是不安全的

大多数使用UNIX时间戳(以及86400将其转换为天)的答案都做出了两个假设,这些假设加在一起可能会导致难以跟踪错误的结果微妙的错误的情况,甚至在成功部署后几天、几周或几个月出现。解决方案并不是不起作用——它起作用了。今天。但它可能明天就停止工作了。

第一个错误是没有考虑到当被问到“从昨天到现在已经过了多少天?”时,如果在“昨天”所指的现在和瞬间之间已经过去了不到一整天,计算机可能会如实回答

通常在将“day”转换为UNIX时间戳时,获得的是该特定日期的午夜的时间戳。

因此,从10月1日午夜到10月15日,已经过去了15天。但是在10月1日13:00到10月15日14:55之间,十五天减五分钟已经过去,大多数解决方案使用floor()或进行隐式整数转换将比预期少报告一天

因此,“多少天前是Y-m-d H: i: s”?将产生错误的答案

第二个错误是将一天等同于86400秒。这是几乎总是正确的——它经常发生,足以忽略它没有发生的时间。但是,当夏令时起作用时,连续两个午夜之间的秒距离是肯定而不是86400,一年至少有两次。跨越夏令时边界比较两个日期将产生错误的答案。

因此,即使您使用强制所有日期时间戳为固定小时的“黑客”,例如午夜(当您仅指定日-月-年而不是小时-分钟-秒时,各种语言和框架也会隐式完成;在MySQL等数据库中,DATE类型也是如此),广泛使用的公式

 FLOOR((unix_timestamp(DATE2) - unix_timestamp(DATE1)) / 86400)

 floor((time() - strtotime($somedate)) / 86400)

当DATE1和DATE2在一年中的同一DST段时,将返回,例如,17;但即使小时:分钟:第二部分相同,参数可能是17.042,更糟糕的是,当它们在不同的DST段并且时区是DST感知的时,参数可能是16.958。然后,使用地板()或任何隐式截断为整数将把应该是17的转换为16。在其他情况下,像“$day>17”这样的表达式将返回17.042的true,即使这看起来好像经过的天数是18。

由于代码不是便携式跨平台,事情变得更加丑陋,因为他们中的一些人可能会应用闰秒,有些人可能不会。在那些的平台上,两个日期之间的差异不会是86400,而是86401,或者86399。因此,在5月有效并通过所有测试的代码将在明年6月中断,届时12.99999天被视为12天而不是13天。2015年有效的两个日期在2017年将不起作用——相同日期,这两个日期都不是闰年。并且在2018-03-01和2017-03-01之间,在那些关心的平台上,366天将过去而不是365天,使2018年成为闰年(事实并非如此)。

因此,如果您真的想使用UNIX时间戳:

  • 明智地使用round()函数,而不是floor()

  • 作为替代方案,请勿计算D1-M1-YYY1和D2-M2-YYY2之间的差异。这些日期将真正被视为D1-M1-YYY1 00:00:00和D2-M2-YYY2 00:00:00。相反,请在D1-M1-YYY1 22:30:00和D2-M2-YYY2 04:30:00之间进行转换。您将总是获得大约二十小时的剩余时间。这可能会变成二十一小时或十九小时,也许是十八小时五十九分三十六秒。没关系。它是一个大保证金,将留在那里并在可预见的未来保持积极。现在您可以安全地使用floor()截断它。

正确解决方案,为了避免魔术常数,舍入散乱和维护债务,是

  • 使用时间库(Datetime、Carbon等);不要自己滚动

  • 使用非常糟糕的日期选择来编写全面的测试用例——跨越DST边界,跨越闰年,跨越闰秒,等等,以及普通的日期。理想情况下(对datetime的调用是快速!)通过从字符串中按顺序组装日期来生成整整四年(又一天)值的日期,并确保第一天和测试日之间的差异稳步增加一。这将确保如果低级例程中有任何变化,修复试图造成破坏,至少你会知道

  • 与测试套件的其余部分一起定期运行这些测试。它们是毫秒的问题,可能会让您从字面上小时省去头疼。


无论你的解决方案是什么,测试它!

下面的函数funcdiff实现了现实世界场景中的一个解决方案(碰巧是公认的解决方案)。

<?php
$tz         = 'Europe/Rome';
$yearFrom   = 1980;
$yearTo     = 2020;
$verbose    = false;


function funcdiff($date2, $date1) {
$now        = strtotime($date2);
$your_date  = strtotime($date1);
$datediff   = $now - $your_date;
return floor($datediff / (60 * 60 * 24));
}
########################################


date_default_timezone_set($tz);
$failures   = 0;
$tests      = 0;


$dom = array ( 0, 31, 28, 31, 30,
31, 30, 31, 31,
30, 31, 30, 31 );
(array_sum($dom) === 365) || die("Thirty days hath September...");
$last   = array();
for ($year = $yearFrom; $year < $yearTo; $year++) {
$dom[2] = 28;
// Apply leap year rules.
if ($year % 4 === 0)   { $dom[2] = 29; }
if ($year % 100 === 0) { $dom[2] = 28; }
if ($year % 400 === 0) { $dom[2] = 29; }
for ($month = 1; $month <= 12; $month ++) {
for ($day = 1; $day <= $dom[$month]; $day++) {
$date = sprintf("%04d-%02d-%02d", $year, $month, $day);
if (count($last) === 7) {
$tests ++;
$diff = funcdiff($date, $test = array_shift($last));
if ((double)$diff !== (double)7) {
$failures ++;
if ($verbose) {
print "There seem to be {$diff} days between {$date} and {$test}\n";
}
}
}
$last[] = $date;
}
}
}


print "This function failed {$failures} of its {$tests} tests";
print " between {$yearFrom} and {$yearTo}.\n";

结果是,

This function failed 280 of its 14603 tests

恐怖故事:“节省时间”的代价

这一切始于2014年末。为了节省几微秒的计算时间,一位聪明的程序员决定在几处插入臭名昭著的“(Midnight OfDateB-Midnight OfDateA)/86400”代码。这是一个显而易见的优化,他甚至没有记录下来,而这个优化通过了集成测试,并以某种方式潜伏在代码中几个月,所有人都没有注意到。

这发生在一个计算几个畅销销售人员工资的程序中,其中最小的一个人的影响力比一个卑微的五人程序员团队加起来还要大得多。2015年3月28日,夏季时区开始,bug了——这些人中的一些被拖欠了一整天的丰厚佣金。更糟糕的是,他们中的大多数人周日不工作,临近月底时,利用这一天赶上了他们的发票。他们绝对被没有逗乐了。

更糟糕的是,他们失去了(已经很少)对程序没有的信心,该程序被设计为秘密地轴它们,并假装-和获得-一个完整的,详细的代码审查,用外行的术语运行和评论测试用例(加上接下来几周的大量红地毯治疗)。

我能说什么呢:从好的方面来说,我们摆脱了很多技术债务,并且能够重写和重构意大利面条的几块碎片,这些碎片可以追溯到90年代摇摆的COBOL侵扰。该程序现在无疑运行得更好了,并且有更多的调试信息可以在任何看起来可疑的时候快速归零。我估计在可预见的未来,仅仅这最后一件事就可以每月节省一到两个人工日,所以灾难有银色,甚至金色的衬里。

不利的一面是,整个骚乱使公司损失了大约20万欧元-加上面子,无疑还有一些议价能力(因此,更多的钱)。

负责“优化”的那个人在2014年12月换了工作,那是在灾难发生之前很久的事了。但还是有人说要起诉他,要求他赔偿损失。高层不太同意“最后那个人的错”——这看起来像是给我们设的圈套,让我们把事情说清楚。最后,在那一年剩下的时间里,我们一直被冷落。那年夏末,团队的一个人辞职了。

(例如,在PHP中,strtotime()将忽略DST,并报告在10月的最后一个星期六的午夜和接下来的星期一的午夜之间,正好过去了2*24*60*60秒,即使这显然是不是真的…并且两个错误将很高兴地使一个正确)。

女士们,先生们,这是一个实例,但事实并非如此。就像安全气囊和安全带一样,你可能永远不会真的需要DateTimeCarbon的复杂性(和易用性)。但是当你可能的那一天(或者你必须证明的那一天,你会想到这一点)会像夜里的小偷一样到来(可能在10月某个周日的02:00)。做好准备。

好吧,选择的答案不是最正确的,因为它会在UTC之外失败。 根据时区(列表),可能会有时间调整创建“没有”24小时的天数,这将使计算(60*60*24)失败。

这是它的一个例子:

date_default_timezone_set('europe/lisbon');
$time1 = strtotime('2016-03-27');
$time2 = strtotime('2016-03-29');
echo floor( ($time2-$time1) /(60*60*24));
^-- the output will be **1**

所以正确的解决方案是使用DateTime

date_default_timezone_set('europe/lisbon');
$date1 = new DateTime("2016-03-27");
$date2 = new DateTime("2016-03-29");


echo $date2->diff($date1)->format("%a");
^-- the output will be **2**

这个管用!

$start = strtotime('2010-01-25');
$end = strtotime('2010-02-20');


$days_between = ceil(abs($end - $start) / 86400);
$early_start_date = date2sql($_POST['early_leave_date']);




$date = new DateTime($early_start_date);
$date->modify('+1 day');




$date_a = new DateTime($early_start_date . ' ' . $_POST['start_hr'] . ':' . $_POST['start_mm']);
$date_b = new DateTime($date->format('Y-m-d') . ' ' . $_POST['end_hr'] . ':' . $_POST['end_mm']);


$interval = date_diff($date_a, $date_b);




$time = $interval->format('%h:%i');
$parsed = date_parse($time);
$seconds = $parsed['hour'] * 3600 + $parsed['minute'] * 60;
//        display_error($seconds);


$second3 = $employee_information['shift'] * 60 * 60;


if ($second3 < $seconds)
display_error(_('Leave time can not be greater than shift time.Please try again........'));
set_focus('start_hr');
set_focus('end_hr');
return FALSE;
}
<?php
$date1=date_create("2013-03-15");
$date2=date_create("2013-12-12");
$diff=date_diff($date1,$date2);
echo $diff->format("%R%a days");
?>

使用上面的代码非常简单。谢谢。

function get_daydiff($end_date,$today)
{
if($today=='')
{
$today=date('Y-m-d');
}
$str = floor(strtotime($end_date)/(60*60*24)) - floor(strtotime($today)/(60*60*24));
return $str;
}
$d1 = "2018-12-31";
$d2 = "2018-06-06";
echo get_daydiff($d1, $d2);

使用这个简单的函数。声明函数

<?php
function dateDiff($firstDate,$secondDate){
$firstDate = strtotime($firstDate);
$secondDate = strtotime($secondDate);


$datediff = $firstDate - $secondDate;
$output = round($datediff / (60 * 60 * 24));
return $output;
}
?>

在你想要的地方调用这个函数

<?php
echo dateDiff("2018-01-01","2018-12-31");


// OR


$firstDate = "2018-01-01";
$secondDate = "2018-01-01";
echo dateDiff($firstDate,$secondDate);
?>

您可以通过以下方式找到日期

<?php
$start  = date_create('1988-08-10');
$end    = date_create(); // Current time and date
$diff   = date_diff( $start, $end );


echo 'The difference is ';
echo  $diff->y . ' years, ';
echo  $diff->m . ' months, ';
echo  $diff->d . ' days, ';
echo  $diff->h . ' hours, ';
echo  $diff->i . ' minutes, ';
echo  $diff->s . ' seconds';
// Output: The difference is 28 years, 5 months, 19 days, 20 hours, 34 minutes, 36 seconds


echo 'The difference in days : ' . $diff->days;
// Output: The difference in days : 10398

PHP中两个日期之间的天数

      function dateDiff($date1, $date2)  //days find function
{
$diff = strtotime($date2) - strtotime($date1);
return abs(round($diff / 86400));
}
//start day
$date1 = "11-10-2018";
// end day
$date2 = "31-10-2018";
// call the days find fun store to variable
$dateDiff = dateDiff($date1, $date2);


echo "Difference between two dates: ". $dateDiff . " Days ";

计算两个日期之间的差异:

$date1=date_create("2013-03-15");
$date2=date_create("2013-12-12");


$diff=date_diff($date1,$date2);


echo $diff->format("%R%a days");

输出: 272天

date_diff()函数返回两个DateTime对象之间的差值。

您可以尝试下面的代码:

$dt1 = strtotime("2019-12-12"); //Enter your first date
$dt2 = strtotime("12-12-2020"); //Enter your second date
echo abs(($dt1 - $dt2) / (60 * 60 * 24));

查找两个日期之间天数差异的最简单方法

$date1 = strtotime("2019-05-25");
$date2 = strtotime("2010-06-23");


$date_difference = $date2 - $date1;


$result =  round( $date_difference / (60 * 60 * 24) );


echo $result;
$diff = strtotime('2019-11-25') - strtotime('2019-11-10');
echo abs(round($diff / 86400));

查看所有答案,我编写了适用于所有PHP版本的通用函数。

if(!function_exists('date_between')) :
function date_between($date_start, $date_end)
{
if(!$date_start || !$date_end) return 0;


if( class_exists('DateTime') )
{
$date_start = new DateTime( $date_start );
$date_end   = new DateTime( $date_end );
return $date_end->diff($date_start)->format('%a');
}
else
{
return abs( round( ( strtotime($date_start) - strtotime($date_end) ) / 86400 ) );
}
}
endif;

一般来说,我使用'DateTime'来查找两个日期之间的天数。但如果出于某种原因,某些服务器设置没有启用'DateTime',它将使用'strtotime()'进行简单(但不安全)的计算。

我阅读了所有以前的解决方案,没有一个使用PHP 5.3工具:DateTime::Diff和DateInterval::Days

DateInterval::Days包含日期之间的正确天数。没有必要创建一些特殊和奇怪的东西。

/**
* We suppose that PHP is configured in UTC
* php.ini configuration:
* [Date]
* ; Defines the default timezone used by the date functions
* ; http://php.net/date.timezone
* date.timezone = UTC
* @link http://php.net/date.timezone
*/


/**
* getDaysBetween2Dates
*
* Return the difference of days between $date1 and $date2 ($date1 - $date2)
* if $absolute parameter is false, the return value is negative if $date2 is after than $date1
*
* @param DateTime $date1
* @param DateTime $date2
* @param Boolean $absolute
*            = true
* @return integer
*/
function getDaysBetween2Dates(DateTime $date1, DateTime $date2, $absolute = true)
{
$interval = $date2->diff($date1);
// if we have to take in account the relative position (!$absolute) and the relative position is negative,
// we return negatif value otherwise, we return the absolute value
return (!$absolute and $interval->invert) ? - $interval->days : $interval->days;
}


echo '<h3>2020-03-01 - 2020-02-01: 29 days as it\'s a standard leap year</h3>';
echo getDaysBetween2Dates(new DateTime("2020-03-01"), new DateTime("2020-02-01"), false);


echo '<h3>1900-03-01 - 1900-02-01: 28 days as it\'s a "standard" century</h3>';
echo getDaysBetween2Dates(new DateTime("1900-03-01"), new DateTime("1900-02-01"), false);


echo '<h3>2000-03-01 - 2000-02-01: 29 days as it\'s a century multiple of 400: 2000=400x5</h3>';
echo getDaysBetween2Dates(new DateTime("2000-03-01"), new DateTime("2000-02-01"), false);


echo '<h3>2020-03-01 - 2020-04-01: -28 days as 2020-03-01 is before 2020-04-01</h3>';
echo getDaysBetween2Dates(new DateTime("2020-02-01"), new DateTime("2020-03-01"), false);

我已经尝试了几乎所有的答案。但是DateTime和date_create都没有在我所有的测试案例中给我正确的答案。特别是测试2月和3月的日期或12月和1月的日期。

所以,我想到了混合溶液。

public static function getMonthsDaysDiff($fromDate, $toDate, $includingEnding = false){
$d1=new DateTime($fromDate);
$d2=new DateTime($toDate);
if($includingEnding === true){
$d2 = $d2->modify('+1 day');
}
$diff = $d2->diff($d1);
$months = (($diff->format('%y') * 12) + $diff->format('%m'));


$lastSameDate = $d1->modify("+$months month");
$days = date_diff(
date_create($d2->format('Y-m-d')),
date_create($lastSameDate->format('Y-m-d'))
)->format('%a');


$return = ['months' => $months,
'days' => $days];
}

我知道,性能方面这相当昂贵。你也可以扩展它以获得年。

这段代码为我工作并使用PHP 8版本进行了测试:

function numberOfDays($startDate, $endDate)
{
//1) converting dates to timestamps
$startSeconds = strtotime($startDate);
$endSeconds = strtotime($endDate);
   

//2) Calculating the difference in timestamps
$diffSeconds = $startSeconds  - $endSeconds;
     

    

//3) converting timestamps to days
$days=round($diffSeconds / 86400);
    

/*  note :
1 day = 24 hours
24 * 60 * 60 = 86400 seconds
*/
   

//4) printing the number of days
printf("Difference between two dates: ". abs($days) . " Days ");
    

return abs($days);
}