PHP:如何检查一个UNIX TIMESTAMP范围是否与任何UNIX TIMESTAMP范围重叠



如何检查一个Unix Timestamp范围是否与PHP中的另一个Unix时间戳范围重叠?

我正在开发一个将来保留的应用程序。但是,每个时期仅允许一(1)个预订


示例

MR。X可以预订资源,从上午10:00。后来,Y女士想从上午8:00保留相同的资源。我的申请应拒绝 Y女士的尝试预订,因为它重叠


我将现有预订的开始和结束时间存储在Unix时间戳(整数)中,但是我可以将它们转换为以下格式" yyyy-mm-dd hh:mm:mm:ss",如果需要,如果需要,反之亦然。<<<<<<<<<<<<<<<<<。/p>

我不明白如何解决这个问题。如果我以所有现有的预订开始时间检查新的开始时间,并且以类似方式检查新的结束时间,则逻辑将具有许多if语句,并使应用程序缓慢。

您是否请帮助我以有效的方式解决此问题,而无需使用大量服务器资源。

非常感谢您的帮助。

谢谢

简介

换句话说,您需要对特定资源进行比较(UNIX时间戳),以确定新的预订是否有效(在域内于新的预订)。

步骤1

首先,类似于此的SQL查询可能会有所帮助。诸如ANYALLNOTEXISTS等关键词似乎很诱人,但在计划冲突(基于UI)时,您必须决定您需要多少信息。此查询提供了提供有关潜在保留的最大信息(在PHP等中的最大信息)的机会。向前看。

// A query like this might help. It's not perfect, but you get the idea.
// This query looks for ALL potential conflicts, starting and ending.
    $sql = "SELECT DISTINCT `t1`.`startTime`, `t1`.`endTime`
              FROM `reservations` AS `t1`
             INNER JOIN `resources` AS `t2`
                ON `t1`.`resourceId` = `t2`.`resourceId`
             WHERE `t2`.`resourceId` = :resourceId
               AND (`t1`.`startTime` BETWEEN :minTime1 AND :maxTime1)
                OR (`t1`.`endTime` BETWEEN :minTime2 AND :maxTime2)
             ORDER BY `t1`.`startTime` ASC";

可能。这将为您提供多维数组。以下逻辑允许您获得报告详细信息为什么不能进行预订。您可以在另一个模块中解释报告。

步骤2

概括 作为Reservation类的方法解决方案。根据您的RDBMS,您可以在SQL中进行类似的操作。虽然,它可能是的特定特定性要少得多,您可能希望粒度稍后。您可以以JSON格式将报告发送到JavaScript前端(只是要考虑的事情)。

private function inOpenDomain(array $exclusion, $testStart, $testEnd)
{
    $result = null;
    $code   = null;
    $start = $exclusion[0];
    $end   = $exclusion[1];
    if (($testStart > $end) || ($testEnd < $start)) {
        $result = true;
        $code = 0;  //Good! No conflict.
    } elseif ($testStart === $start) {
        $result = false;
        $code = 1;
    } elseif ($testStart === $end) {
        $result = false;
        $code = 2;
    } elseif ($testEnd === $start) {
        $result = false;
        $code = 3;
    } elseif ($testEnd === $end) {
        $result = false;
        $code = 4;
    } elseif (($testStart > $start) && ($testEnd < $end)) {   //Middle
        $result = false;
        $code = 5;
    } elseif (($testStart < $start) && ($testEnd > $start)) { //Left limit
        $result = false;
        $code = 6;
    } elseif (($testStart < $end) && ($testEnd > $end)) {     //Right limit
        $result = false;
        $code = 7;
    } elseif (($testStart < $start) && ($testEnd > $end)) {   //Both limits
        $result = false;
        $code = 8;
    } else {
        $result = false;
        $code = 9;
    }
    return ['start' => $start, 'end' => $end, 'result' => $result => 'code' => $code];
}

步骤3

制作一种管理先前预订时间检查的方法(假设PDO::FETCH_ASSOC)。

private function checkPeriods(array $periods, $newStartTime, $newEndTime)
{
    $report = [];
    if (!isset($periods[0])) { //If NOT multi-dimensional
        $report = inOpenDomain($periods, $newStartTime, $newEndTime)
    } else {
        for ($i = 0, $length = $count($periods); $i < $length; ++$i) {
            $report[$i] = inOpenDomain($periods[$i], $newStartTime, $newEndTime);
        }
    }
    return $report;
}

步骤4

时尚一种使用PDO准备的语句在reservations表上执行SELECT的方法。通常,...

private function getReservationTimes($resourceId, $minTime, $maxTime) 
{
    $sql = "SELECT DISTINCT `t1`.`startTime`, `t1`.`endTime`
              FROM `reservations` AS `t1`
             INNER JOIN `resources` AS `t2`
                ON `t1`.`resourceId` = `t2`.`resourceId`
             WHERE `t2`.`resourceId` = :resourceId
               AND (`t1`.`startTime` BETWEEN :minTime1 AND :maxTime1)
                OR (`t1`.`endTime` BETWEEN :minTime2 AND :maxTime2)
             ORDER BY `t1`.`startTime` ASC";
    $stmt = $this->db->prepare($sql);
    $stmt->bindParam(:resourceId , $resourceId);
    $stmt->bindParam(:minTime1 , $minTime);
    $stmt->bindParam(:maxTime1 , $maxTime);
    $stmt->bindParam(:minTime2 , $minTime);
    $stmt->bindParam(:maxTime2 , $maxTime);
    $stmt->execute();
    return $stmt->fetchAll();
}

步骤5

在整个过程中制作公共方法(接口)。

public function isOpen($minTime, $maxTime)
{
    $periods = $this->getReservationTimes($this->resource->getResourceId(), $minTime, $maxTime);
    if (empty($periods)) {
        return true;  //You may reserve the resource during the time period.
    }
    return $this->checkPeriods($periods, $this->start, $this->end));  
}

步骤6

将关注点分开。

为要保留的实际项目创建类层次结构。

abstact class Product
{
}
class Resource extends Product implements Reservable  //Or, something ...
{
    private $resourceId;
   //etc ....
}

为预订创建类层次结构。

abstract class Interval
{
    private $start;
    private $end;
    public function __construct($start, $end)
    {
        $this->start = $start;
        $this->end   = $end;
    }
}
class Reservation extends Interval
{
    private $db;
    private $resource;
    public function __construct(PDO $pdo, Reservable $resource, $reqStartTime, $reqEndTime)
    {
        parent::__construct($reqStartTime, $reqEndTime);
        $this->db = $pdo;
        $this->resource = $resource;
    }
}

步骤7

在try/catch

中运行

当您实例化Reservation对象时,至少提供Reservable对象,请求的开始时间和请求的结束时间(在这种情况下为Unix Timestamps)。

try
{
    $day          = 84600;                   // Seconds per day.
    $future       = $day * 90;               // Application specific.
    //User requested times.
    $reqStartTime = 1488394687 + $day;       // Tomorrow.
    $reqEndTime   = 1488394687 + ($day * 2); // Two day duration.
    //Search constraints.
    $minTime      = time();                   // Today. Right now.
    $maxTime      = 1488394687 + $future;     // 90 day look ahead.
    $reservation  = new Reservation($pdo, $resourceObj, $reqStartTime, $reqEndTime);
    $availability = $reservation->isOpen($minTime, $maxTime);
    if($availability === true){
        $reservation->confirm();
    } else {
        //Have some other object deal with the report
        $reporter = new Reporter($availability);
        $reporter->analyzeReport();
        //Have some other object update the view, etc ...
    }
}
catch(Exception $e)
{
    //Handle it.
}

最新更新