PHP检查日期是否在两个日期之间

97

我从Stackoverflow上得到了这段代码,并稍作修改以使其适用于今天的日期。

我想检查今天是否在两个日期之间。但是它好像不能正常工作。 我错过了什么吗?

$paymentDate = date('d/m/Y');
echo $paymentDate; // echos today! 
$contractDateBegin = date('d/m/Y', '01/01/2001');
$contractDateEnd = date('d/m/Y', '01/01/2015');

if ($paymentDate > $contractDateBegin && $paymentDate < $contractDateEnd)
{
  echo "is between";
}
else
{
echo "NO GO!";  
}

2
如果你使用的是PHP5,请查看http://no2.php.net/manual/en/datetime.diff.php上的datetime.diff函数。 - Tom
你真的想使用date()或strtotime()吗? - Mark Baker
我使用了strtotime,但仍然得到了“No Go!”的错误提示。 - Papa De Beau
然后,您应该阅读strtotime()接受的格式……但使用date()绝对是错误的函数。 - Mark Baker
为什么是-1?这似乎是一个好问题。我放置了我的代码并得到了一些好的评论。我认为这可能对其他人有所帮助。 - Papa De Beau
17个回答

225

只需使用 strtotime() PHP 函数即可。

$paymentDate = date('Y-m-d');
$paymentDate=date('Y-m-d', strtotime($paymentDate));
//echo $paymentDate; // echos today! 
$contractDateBegin = date('Y-m-d', strtotime("01/01/2001"));
$contractDateEnd = date('Y-m-d', strtotime("01/01/2012"));
    
if (($paymentDate >= $contractDateBegin) && ($paymentDate <= $contractDateEnd)){
    echo "is between";
}else{
    echo "NO GO!";  
}

注意:使用<=>=来计算今天的日期。

谢谢您,先生!也许最好删除您在顶部添加的答案,只留下适合我的那个。不确定。 - Papa De Beau
8
@PapaDeBeau:你必须记住,这个解决方案中的“01/01/2001”日期是以“m/d/Y”格式而不是“d/m/Y”格式表示的。 - Jon
5
我不会使用严格比较,所以这是最好的 $paymentDate >= $contractDateBegin and $paymentDate <= $contractDateEnd。 - pollux1er
3
这个页面上的所有解决方案,包括这个解决方案,在你输入早于 Unix 纪元的日期时都会失败。尝试使用1942年7月28日进行测试,看看会发生什么。 - Alex Barker
这个解决方案只有在您知道哪个日期是早期的,哪个日期是晚期的情况下才有效。如果您从数据库中获取这些日期并且不知道它们的顺序,那么它将失败。 - Thomas Weller
显示剩余3条评论

42

你不能直接比较日期字符串。最好使用 PHP 的 DateTime 对象:

$paymentDate = new DateTime(); // Today
echo $paymentDate->format('d/m/Y'); // echos today! 
$contractDateBegin = new DateTime('2001-01-01');
$contractDateEnd  = new DateTime('2015-01-01');

if (
  $paymentDate->getTimestamp() > $contractDateBegin->getTimestamp() && 
  $paymentDate->getTimestamp() < $contractDateEnd->getTimestamp()){
  echo "is between";
}else{
   echo "NO GO!";  
}

@PapaDeBeau:在 PHP 版本低于 5 的情况下无法使用。<?php echo phpversion(); ?> 输出什么? - Amal Murali
1
看起来 getTimestamp() 只支持 5.3 版本... 但它在 2009 年就发布了 :) - luttkens
2
如果在$contractDateEnd与当前日期相同时打印$paymentDate->getTimestamp()和$contractDateEnd->getTimestamp(),它将产生错误的结果。例如今天是2015年1月5日,但如果你改变$contractDateEnd = new DateTime('2015-05-01');,那么它将产生错误的时间戳。你应该使用$paymentDate = new DateTime('2015-05-01')而不是仅仅使用$paymentDate = new DateTime();,即向它传递当前日期。 - RN Kushwaha
1
我一直在想,为什么人们不经常使用DateTime? - vaso123
1
这里不需要使用 getTimestamp() - But those new buttons though..
显示剩余4条评论

19
如果时间很重要:
$paymentDate = strtotime(date("Y-m-d H:i:s"));
$contractDateBegin = strtotime("2014-01-22 12:42:00");
$contractDateEnd = strtotime("2014-01-22 12:50:00");

if($paymentDate > $contractDateBegin && $paymentDate < $contractDateEnd) {
   echo "is between";
} else {
    echo "NO GO!";  
}    

6

基于Luttken的答案,我想再加上我的一些看法 :)

function dateIsInBetween(\DateTime $from, \DateTime $to, \DateTime $subject)
{
    return $subject->getTimestamp() > $from->getTimestamp() && $subject->getTimestamp() < $to->getTimestamp() ? true : false;
}

$paymentDate       = new \DateTime('now');
$contractDateBegin = new \DateTime('01/01/2001');
$contractDateEnd   = new \DateTime('01/01/2016');

echo dateIsInBetween($contractDateBegin, $contractDateEnd, $paymentDate) ? "is between" : "NO GO!";

在我看来,这个答案值得成为一个解决方案。 - P-A

5
您正在将日期作为字符串进行比较,这样做是行不通的,因为比较是按字典序进行的。这与对文本文件进行排序时出现的问题相同,其中一行20会出现在一行100之后,因为内容不被视为数字,而是作为ASCII代码序列处理。此外,创建的日期都是错误的,因为您使用了一个字符串格式字符串,而预期需要一个时间戳(第二个参数)。
相反,您应该比较DateTime对象的时间戳,例如:
 $paymentDate = date_create();
 $contractDateBegin = date_create_from_format('d/m/Y', '01/01/2001');
 $contractDateEnd = date_create_from_format('d/m/Y', '01/01/2015');

您现有的条件将能够正常运行。

尝试使用 date_create - Ofir Baruch
2
@PapaDeBeau:date_create_from_format 函数是在 PHP 5.3 中引入的,而该版本已经到达生命周期终点 -- 然而您正在使用更早的版本。如果可能的话,我建议您立即升级。 - Jon
@OfirBaruch:不起作用,因为“d/m/Y”不是支持的格式之一。 - Jon
下投票者:这个答案有什么问题吗?请帮助我通过留下评论来改进它。 - Jon
@Jon,我的问题也被踩了。我认为这是一个好问题,并且符合Stack的要求。 - Papa De Beau
显示剩余3条评论

4

另一种解决方案是将日期写成Ymd的格式。

以这种“格式”书写,比较日期要容易得多。

$paymentDate       = date('Ymd'); // on 4th may 2016, would have been 20160504
$contractBegin     = 20010101;
$contractEnd       = 20160101;
echo ($paymentDate >= $contractBegin && $paymentDate <= $contractEnd) ? "Between" : "Not Between";

这段代码将在一年中的任何一天都能正常工作,并且不依赖于任何函数或转换(PHP将考虑$paymentDate的整数值与contractBegincontractEnd的整数值进行比较)。


3

因为我很懒:

$paymentDate = new DateTime();
$contractStartDate = new Datetime('01/01/2001');
$contractEndDate = new Datetime('01/01/2015');
$payable = $paymentDate < $contractEndDate && $contractStartDate > $paymentDate; //bool

var_dump($payable)

显示:

bool(false)

作为一个函数
function isPayable(DateTime $payDate, DateTime $startDate, DateTime $endDate):bool 
{
    return $payDate > $startDate && $payDate < $endDate;
}

var_dump(isPayable(new DateTime(), new Datetime('01/01/2001'), new DateTime('01/01/2015')));
var_dump(isPayable(new DateTime('2003-03-15'), new Datetime('2001-01-01'), new DateTime('2015-03-01')));



显示:

bool(false)
bool(True)

2
需要注意的是,您可以直接比较 Datetime() 对象。因此,以下是 @luttkens 的答案的简化和清晰版本:
$paymentDate       = new DateTime(); // Today
$contractDateBegin = new DateTime('2001-01-01');
$contractDateEnd   = new DateTime('2015-01-01');

if ($paymentDate >= $contractDateBegin && $paymentDate < $contractDateEnd) {
  // is in between
}

0
如果您需要括号内的日期是动态的...
$todayStr = date('Y-m-d');
$todayObj=date('Y-m-d', strtotime($todayStr));
$currentYrStr =  date('Y');
$DateBegin = date('Y-m-d', strtotime("06/01/$currentYrStr"));
$DateEnd = date('Y-m-d', strtotime("10/01/$currentYrStr"));
if (($todayObj > $contractDateBegin) && ($paymentDate < $contractDateEnd)){
    $period="summer";
}else{
   $period="winter";  
}

0

简单的解决方案:

function betweenDates($cmpDate,$startDate,$endDate){ 
   return (date($cmpDate) > date($startDate)) && (date($cmpDate) < date($endDate));
}

你可以解释一下这个的用法吗? - Ingus
这绝对有效,如果你解析了3个Unix时间戳值的话,谢谢@Spock! - AdamJones

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接