/**
* 获取下次执行时间
*
* @param int $type 类型
* @param int|string $cycle 执行规则
* @param int $time 当前时间
* @param int $lastExecutionTime 最后执行时间
* @return integer
*/
public function getNextExecutionTime($type, $cycle, $time, $lastExecutionTime = 0): int
{
switch ($type) {
case 1: // N分钟 1 每隔1分钟执行
$dateTime = new \DateTime(date('Y-m-d H:i:s', $lastExecutionTime));
// 添加间隔时间
$dateTime->modify("+{$cycle} minutes");
$clockTime = $dateTime->getTimestamp();
if($clockTime < $time) $clockTime = $time;
break;
case 2: // N小时 2/3 每隔2时 第3分执行
$arrayDate = explode('/', $cycle);
$dateTime = new \DateTime(date('Y-m-d H:i:s', $lastExecutionTime));
// 计算下一个执行时间
$nextExecutionTimeObj = clone $dateTime;
$nextExecutionTimeObj->setTime((int) $dateTime->format('H'), (int) $arrayDate[1], 0);
if ($dateTime >= $nextExecutionTimeObj) {
$nextExecutionTimeObj->modify("+{$arrayDate[0]} hours");
}
$clockTime = $nextExecutionTimeObj->getTimestamp();
break;
case 3: // 每小时 -- 2 每时 2分执行
$dateTime = new \DateTime(date('Y-m-d H:i:s', $time));
// 计算下一个执行时间
$nextExecutionTimeObj = clone $dateTime;
$nextExecutionTimeObj->setTime((int) $dateTime->format('H'), (int) $cycle, 0);
// 如果当前时间已经过了设定的执行时间,则设定为明天的相同时间
if ($dateTime >= $nextExecutionTimeObj) {
$nextExecutionTimeObj->modify('+1 hours');
}
$clockTime = $nextExecutionTimeObj->getTimestamp();
break;
case 4: // 每天 -- 0/1 每天 0时 1分执行
$arrayDate = explode('/', $cycle);
$dateTime = new \DateTime(date('Y-m-d H:i:s', $time));
// 计算下一个执行时间
$nextExecutionTimeObj = clone $dateTime;
$nextExecutionTimeObj->setTime((int) $arrayDate[0], (int) $arrayDate[1], 0);
// 如果当前时间已经过了设定的执行时间,则设定为明天的相同时间
if ($dateTime >= $nextExecutionTimeObj) {
$nextExecutionTimeObj->modify('+1 day');
}
$clockTime = $nextExecutionTimeObj->getTimestamp();
break;
case 5: // N天 -- 1/0/1 每1天 0时 1分执行
$arrayDate = explode('/', $cycle);
$dateTime = new \DateTime(date('Y-m-d H:i:s', $lastExecutionTime));
// 计算下一个执行时间
$dateTime->modify("+{$arrayDate[0]} days");
$dateTime->setTime((int) $arrayDate[1], (int) $arrayDate[2], 0);
$clockTime = $dateTime->getTimestamp();
break;
case 6: // 每星期 4/3/5 每周4 3时 5分执行
$arrayDate = explode('/', $cycle);
$dateTime = new \DateTime(date('Y-m-d H:i:s', $time));
// 设置执行时间为每周一的16时4分
$nextExecutionTimeObj = clone $dateTime;
$nextExecutionTimeObj->setTime((int) $arrayDate[1], (int) $arrayDate[2], 0);
// 如果当前时间已经过了设定的执行时间,则设定为下一周的相同星期和时间
if ($dateTime >= $nextExecutionTimeObj) {
$nextExecutionTimeObj->modify('+1 week');
}
$clockTime = $nextExecutionTimeObj->getTimestamp();
break;
case 7: // 每月 4/3/6 每月 4日 3时 6分执行
$arrayDate = explode('/', $cycle);
$dateTime = new \DateTime(date('Y-m-d H:i:s', $time));
// 设置执行时间为每月的4号5时20分
$dateTime->setDate((int) $dateTime->format('Y'), (int) $dateTime->format('m'), (int) $arrayDate[0]);
$dateTime->setTime((int) $arrayDate[1], (int) $arrayDate[2], 0);
// 如果当前时间已经过了设定时间,则设定为下个月的相同日期和时间
if ($dateTime <= new \DateTime(date('Y-m-d H:i:s', $time))) {
$dateTime->modify('+1 month');
}
$clockTime = $dateTime->getTimestamp();
break;
case 8: // 每年 11/4/3/6 每年 11月 4日 3时 6分执行
$arrayDate = explode('/', $cycle);
$dateTime = new \DateTime(date('Y-m-d H:i:s', $time));
// 设置执行时间为每年的11月4日5时20分
$dateTime->setDate((int) $dateTime->format('Y'), (int) $arrayDate[0], (int) $arrayDate[1]);
$dateTime->setTime((int) $arrayDate[2], (int) $arrayDate[3], 0);
// 如果当前时间已经过了设定时间,则设定为明年的相同日期和时间
if ($dateTime <= new \DateTime(date('Y-m-d H:i:s', $time))) {
$dateTime->modify('+1 year');
}
$clockTime = $dateTime->getTimestamp();
break;
default:
$clockTime = 0;
break;
}
// 兜底
if($clockTime < $time) $clockTime = $time;
return $clockTime;
}
可以配合swoole、workerman 等定时器 进行检索需要执行的事件