【问题标题】:How to check if a date is in a given range?如何检查日期是否在给定范围内?
【发布时间】:2010-11-01 21:03:40
【问题描述】:

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

例如

$start_date = '2009-06-17';

$end_date = '2009-09-05';

$date_from_user = '2009-08-28'; 

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

【问题讨论】:

  • 这会有所帮助,然后您就可以使用任何日期操作功能了。
  • 请注意时间戳限制,因为 Unix 时间戳从 1970 年 1 月 1 日 (1970-01-01) 开始,因此在 1970 年之前测试日期可能会有一些有趣的行为。跨度>
  • @Shadi 你知道有负数之类的东西,对吧?
  • @fiXedd 存在同样的基本问题——即使允许负时间戳,32 位时间戳也不能表示 1902 年之前的日期。

标签: php date date-range


【解决方案1】:

将它们转换为时间戳是可行的方法,例如使用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));
}

【讨论】:

  • 效果很好。谢谢。
【解决方案2】:

如果您有 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);

【讨论】:

  • 您可能会将其转换为一个接受三个参数并返回布尔值的函数。应该很容易测试吗?
  • 我会说函数应该在2012-02-012012-02-01 ... 2014-04-30 23:59:59之间返回true。
  • 我总是更喜欢DateTime,而不是 PHP 提供的开箱即用的粗略时间函数。要在此检查中包含开始和结束日期,只需将返回值更改为 return $date &gt;= $startDate &amp;&amp; $date &lt;= $endDate;
  • @zanderway 你是说 > 默认为“天”比较而不是秒比较? $startDate 指定了秒数,所以我想知道 ">=" 是否真的有必要?
【解决方案3】:

没有必要转换为时间戳来进行比较,因为字符串被验证为“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”,这样字符串比较将不等同于日期或时间戳比较。仅当字符串中的日期值采用 CONSISTENTCANONICAL 格式时才有效。

编辑在此处添加注释,详细说明显而易见的内容。

一致,我的意思是,例如,被比较的字符串必须采用相同的格式:月份必须始终为两个字符,日期必须始终为两个字符,分隔符必须始终做个破折号。我们无法可靠地比较不是四个字符年、两个字符月、两个字符日的“字符串”。例如,如果我们在字符串中混合了一个字符和两个字符月,当我们比较'2009-9-30''2009-10-11' 时,我们会得到意想不到的结果。我们人类认为“9”小于“10”,但字符串比较会看到'2009-9' 大于'2009-1'。我们不一定需要有破折号分隔符;我们可以可靠地比较 'YYYYMMDD' 格式的字符串;如果有分隔符,它必须始终存在并且始终相同。

CANONICAL 是指一种格式,该格式将生成按日期顺序排序的字符串。也就是说,字符串将首先表示“年”,然后是“月”,然后是“日”。我们无法可靠地比较 'MM-DD-YYYY' 格式的字符串,因为这不是规范的。字符串比较会先比较MM(月),然后再比较YYYY(年),因为字符串比较是从左到右进行的。)'YYYY-MM-DD'字符串格式的一大好处是它是典范;以这种格式表示的日期可以可靠地作为字符串进行比较。

[附录]

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

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

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

HTH

【讨论】:

  • 尽管如果 $date_from_user、$start_date 或 $end_date 的值不是日期,则如果不进行强制转换,您可能会遇到问题。即 $end_date = 'Balh Blah'.. 肯定不会工作正确
  • @spencer7593,您对此行为有参考吗?
  • 你可以使用 checkdate() 来验证
  • 这对时间有效吗?我的意思是,我有两次 HH:MM:SS 格式,我想知道这两者之间是否有任何给定时间。
  • @Sergio:是的,相同的字符串比较适用于时间值,只要字符串采用标准规范格式(即 24 小时制,午夜表示为“00:00:00”,午夜前的最后一秒表示为“23:59:59”。为了保证字符串比较“有效”,您需要保证时间值的字符串表示形式是有保证的格式。
【解决方案4】:
$startDatedt = strtotime($start_date)
$endDatedt = strtotime($end_date)
$usrDatedt = strtotime($date_from_user)

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

【讨论】:

  • 不包括任何与开始日期或结束日期完全匹配的内容
  • OP 没有要求包含匹配项。
【解决方案5】:

将两个日期都转换为时间戳然后做

伪代码:

if date_from_user > start_date && date_from_user < end_date
    return true

【讨论】:

  • 您可能需要对其进行编辑,以便在范围内也包括 start_date 和 end_date。现在如果 date_from_user 等于其中之一,则不会被计算在内。
  • OP 没有指定包含或排除范围,所以我将由他们来选择使用哪种策略
【解决方案6】:

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

【讨论】:

  • 此时代码中的日期已经被验证
【解决方案7】:
$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";
}

【讨论】:

    【解决方案8】:

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

    【讨论】:

    • 您能澄清一下“将它们转换为日期”吗?你会怎么做?我以为 PHP 没有日期类型?
    【解决方案9】:

    你可以试试这个:

    //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);
    

    【讨论】:

    • 版本说明:iterator_to_array() 自 PHP 5.1 起可用
    【解决方案10】:

    我发现这个方法最简单:

    $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
    
      }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-01-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-10-04
      相关资源
      最近更新 更多