PHP:如何检查一个 UNIX 时间戳范围是否与任何 UNIX 时间戳范围重叠?
PHP: How do I check if one UNIX timestamp range overlaps any UNIX timestamp range?
如何检查一个 UNIX 时间戳范围是否与 PHP 中的另一个 UNIX 时间戳范围重叠?
我正在开发一个接受未来预订的应用程序。但是,每个时段只允许预订一 (1) 次。
示例:
先生X 预订了从 10:00 A.M. 到 12:00 P.M.(中午)的资源.后来,Y 女士想保留 相同的资源 从 8:00 A.M. 到 11:00 P.M.。我的申请应该拒绝 Y 女士的预订尝试,因为它重叠 X 先生的先前 预订。
我将现有预订的开始和结束时间存储在 UNIX 时间戳(整数)中,但如果需要,我可以将它们转换为以下格式 "yyyy-mm-dd hh:mm:ss",反之亦然。
我不明白如何解决这个问题。如果我用所有现有的预订开始时间检查新的开始时间,并以类似的方式检查新的结束时间,逻辑将有许多 if
语句并使应用程序变慢。
能否请您帮助我以高效的方式解决这个问题,而无需使用大量服务器资源。
非常感谢您的帮助。
谢谢
简介
换句话说,您需要比较特定资源的所有预留间隔(UNIX 时间戳)以确定新预留是否有效(在domain 用于新的预订)。
步骤 1
首先,与此类似的 SQL 查询可能会有所帮助。虽然像 ANY
、ALL
、NOT
、EXISTS
等关键词看起来很诱人,但您可以自行决定在出现问题时需要多少信息调度冲突(基于您的 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
class的方法。根据您的 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 步
时尚一种方法来执行 SELECT
on the reservations
table using a PDO 准备好的语句。一般来说,...
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方法(接口)
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 步
分离关注点。
为实际保留的项目创建一个 class 层次结构。
abstact class Product
{
}
class Resource extends Product implements Reservable //Or, something ...
{
private $resourceId;
//etc ....
}
为预订创建 class 层次结构。
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 时间戳)。
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.
}
如何检查一个 UNIX 时间戳范围是否与 PHP 中的另一个 UNIX 时间戳范围重叠?
我正在开发一个接受未来预订的应用程序。但是,每个时段只允许预订一 (1) 次。
示例:
先生X 预订了从 10:00 A.M. 到 12:00 P.M.(中午)的资源.后来,Y 女士想保留 相同的资源 从 8:00 A.M. 到 11:00 P.M.。我的申请应该拒绝 Y 女士的预订尝试,因为它重叠 X 先生的先前 预订。
我将现有预订的开始和结束时间存储在 UNIX 时间戳(整数)中,但如果需要,我可以将它们转换为以下格式 "yyyy-mm-dd hh:mm:ss",反之亦然。
我不明白如何解决这个问题。如果我用所有现有的预订开始时间检查新的开始时间,并以类似的方式检查新的结束时间,逻辑将有许多 if
语句并使应用程序变慢。
能否请您帮助我以高效的方式解决这个问题,而无需使用大量服务器资源。
非常感谢您的帮助。
谢谢
简介
换句话说,您需要比较特定资源的所有预留间隔(UNIX 时间戳)以确定新预留是否有效(在domain 用于新的预订)。
步骤 1
首先,与此类似的 SQL 查询可能会有所帮助。虽然像 ANY
、ALL
、NOT
、EXISTS
等关键词看起来很诱人,但您可以自行决定在出现问题时需要多少信息调度冲突(基于您的 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
class的方法。根据您的 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 步
时尚一种方法来执行 SELECT
on the reservations
table using a PDO 准备好的语句。一般来说,...
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方法(接口)
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 步
分离关注点。
为实际保留的项目创建一个 class 层次结构。
abstact class Product
{
}
class Resource extends Product implements Reservable //Or, something ...
{
private $resourceId;
//etc ....
}
为预订创建 class 层次结构。
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 时间戳)。
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.
}