如何检查日期是否在给定范围内?


86

如果有$start_date$end_date,如何检查用户给定的日期是否在该范围内?

例如

$start_date = '2009-06-17';

$end_date = '2009-09-05';

$date_from_user = '2009-08-28'; 

目前日期是字符串,将它们转换为时间戳整数是否有帮助?


这会有所帮助,然后您将可以使用其中的任何日期操作功能。
ChrisF

3
请注意时间戳记的限制,因为Unix时间戳记是在1970年1月1日(1970-01-01)的纪元开始的,所以对于1970
。– Shadi Almosri 09年

1
@Shadi你知道有负数之类的东西吧?
杰里米·洛根

@fiXedd尽管存在相同的基本问题-即使允许使用负时间戳,但32位时间戳也不能表示1902
Frank Farmer

Answers:


122

使用strtotime将它们转换为时间戳是正确的方法,例如

$start_date = '2009-06-17';

$end_date = '2009-09-05';

$date_from_user = '2009-08-28';

check_in_range($start_date, $end_date, $date_from_user);


function check_in_range($start_date, $end_date, $date_from_user)
{
  // Convert to timestamp
  $start_ts = strtotime($start_date);
  $end_ts = strtotime($end_date);
  $user_ts = strtotime($date_from_user);

  // Check that user date is between start & end
  return (($user_ts >= $start_ts) && ($user_ts <= $end_ts));
}

效果很好。谢谢。
GeneCode

47

如果您使用的是PHP 5.3以上版本,请使用DateTime类。更易于使用,更好的功能。

DateTime内部支持时区,其他解决方案则由您自己决定。

<?php    
/**
 * @param DateTime $date Date that is to be checked if it falls between $startDate and $endDate
 * @param DateTime $startDate Date should be after this date to return true
 * @param DateTime $endDate Date should be before this date to return true
 * return bool
 */
function isDateBetweenDates(DateTime $date, DateTime $startDate, DateTime $endDate) {
    return $date > $startDate && $date < $endDate;
}

$fromUser = new DateTime("2012-03-01");
$startDate = new DateTime("2012-02-01 00:00:00");
$endDate = new DateTime("2012-04-30 23:59:59");

echo isDateBetweenDates($fromUser, $startDate, $endDate);

您可能会将其转换为带有三个参数的函数,并返回一个布尔值。应该很容易测试?
oldwizard

我想说的是,该函数应该2012-02-01在之间返回true 2012-02-01 ... 2014-04-30 23:59:59
Salman A

2
我总是喜欢DateTimePHP提供的即开即用的粗略时间函数。要在此检查中包括开始和结束日期,只需将返回值更改为return $date >= $startDate && $date <= $endDate;
zanderwar '16

@zanderway您是说>默认为“天”比较而不是秒比较吗?$ startDate指定了秒数,所以我想知道“> =”是否真的必要吗?
PJ Brunet

46

假设字符串已被验证为“ YYYY-MM-DD”规范格式的日期,则不必转换为时间戳进行比较。

此测试将起作用:

( ( $date_from_user >= $start_date ) && ( $date_from_user <= $end_date ) )

给出:

$start_date     = '2009-06-17';
$end_date       = '2009-09-05';
$date_from_user = '2009-08-28';

注意:像这样比较字符串确实允许使用“无效”日期,例如(12月32日)“ 2009-13-32”和格式错误的字符串“ 2009/3/3”,因此字符串比较将不等同于日期或时间戳比较。这只有在字符串中的日期值处于一致的CANONICAL格式。

编辑在此处添加注释,详细说明。

CONSISTENT表示,例如,要比较的字符串必须采用相同的格式:月份必须始终为两个字符,日期必须始终为两个字符,分隔符必须始终为破折号。我们不能可靠地比较不是四个字符年份,两个字符月份,两个字符日期的“字符串”。如果我们有一个字符和字符串两种字符个月的混合,例如,我们希望当我们比较得到意想不到的结果,'2009-9-30''2009-10-11'。我们人类认为“ 9”小于“ 10”,但是字符串比较将看到'2009-9'大于“ 10” '2009-1'。我们不一定需要使用破折号字符;我们可以同样可靠地比较字符串'YYYYMMDD'格式; 如果有分隔符,则必须始终存在且始终相同。

通过CANONICAL,我的意思是一个,这将导致将按照日期顺序进行排序字符串格式。也就是说,字符串将首先具有“年”的表示形式,然后具有“月”的表示形式,然后具有“天”的表示形式。我们不能可靠地比较'MM-DD-YYYY'格式的字符串,因为这不是规范的。因为字符串比较从左到右进行MM,所以字符串比较将比较(月份)之前的(月份)YYYY。以这种格式表示的日期可以可靠地与字符串进行比较。

[附录]

如果确实要进行php时间戳转换,请注意限制。

在某些平台上,php不支持早于1970-01-01和/或晚于2038-01-19的时间戳记值。(这是unix时间戳记32位整数的本质。)应该使用更高版本的pf php(5.3?)解决该问题。

如果从字符串转换为时间戳并从时间戳转换回字符串时,如果不小心使用相同的时区,则时区也可能是一个问题。

高温超导


1
这个很有趣。
Ionuț G. Stan,2009年

1
尽管没有强制转换,但是如果$ date_from_user或$ start_date或$ end_date的值不是日期,则可能会遇到问题。即$ end_date ='Balh Blah'..肯定无法正常工作
Mike Dinescu 2009年

@ spencer7593,您对此行为有一些参考吗?
Ionuț G. Stan 2009年

2
您可以使用checkdate()进行验证
绝对

1
@Sergio:是的,只要字符串采用标准规范格式(即24小时制,午夜表示为“ 00:00:00”,午夜之前的最后一秒表示为“ 。23:59:59'为了保证该字符串比较将‘工作’,你需要保证时间值的字符串表示是在保证格式。
spencer7593

4
$startDatedt = strtotime($start_date)
$endDatedt = strtotime($end_date)
$usrDatedt = strtotime($date_from_user)

if( $usrDatedt >= $startDatedt && $usrDatedt <= $endDatedt)
{
   //..falls within range
}

这将不包括与开始日期或结束日期完全匹配的内容
TheTXI

OP并未要求进行包容性比赛。
杰里米·洛根

3

将两个日期都转换为时间戳,然后执行

伪代码:

if date_from_user > start_date && date_from_user < end_date
    return true

您可能需要对其进行编辑,以便在范围内也包含start_date和end_date。现在,如果date_from_user相等,则不会计数。
TheTXI

OP没有指定包含范围或排除范围,因此我将由他们自行选择使用哪种策略
Glen

3

按照您提供的格式,假设用户足够聪明,可以为您提供有效的日期,则无需先转换为日期,您可以将它们作为字符串进行比较。


1
至此,代码中的日期已经过验证
梅利

3
$start_date="17/02/2012";
$end_date="21/02/2012";
$date_from_user="19/02/2012";

function geraTimestamp($data)
{
    $partes = explode('/', $data); 
    return mktime(0, 0, 0, $partes[1], $partes[0], $partes[2]);
}


$startDatedt = geraTimestamp($start_date); 
$endDatedt = geraTimestamp($end_date);
$usrDatedt = geraTimestamp($date_from_user);

if (($usrDatedt >= $startDatedt) && ($usrDatedt <= $endDatedt))
{ 
    echo "Dentro";
}    
else
{
    echo "Fora";
}

2

将它们转换为日期或时间戳整数,然后仅检查$ date_from_user是否为<= $ end_date和> = $ start_date


3
您能否澄清“将它们转换为日期”?你会怎么做?我以为PHP没有日期类型?
meleyal

2

您可以尝试以下方法:

//custom date for example
$d1 = new DateTime("2012-07-08");
$d2 = new DateTime("2012-07-11");
$d3 = new DateTime("2012-07-08");
$d4 = new DateTime("2012-07-15");

//create a date period object
$interval = new DateInterval('P1D');
$daterange = iterator_to_array(new DatePeriod($d1, $interval, $d2));
$daterange1 = iterator_to_array(new DatePeriod($d3, $interval, $d4));
array_map(function($v) use ($daterange1) { if(in_array($v, $daterange1)) print "Bingo!";}, $daterange);

1
版本说明:iterator_to_array()自PHP 5.1
Raptor

0

我发现此方法最简单:

$start_date = '2009-06-17';
$end_date = '2009-09-05';
$date_from_user = '2009-08-28';

$start_date = date_create($start_date);
$date_from_user = date_create($date_from_user);
$end_date = date_create($end_date);

$interval1 = date_diff($start_date, $date_from_user);
$interval2 = date_diff($end_date, $date_from_user);

if($interval1->invert == 0){
  if($interval2->invert == 1){

     // if it lies between start date and end date execute this code

  }
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.