PHP 定时任务 通过规则获取下次执行时间

/**
     * 获取下次执行时间
     *
     * @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 等定时器 进行检索需要执行的事件

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值