在我正在创建用户的应用程序中,可以安排重复任务.只需生成间隔模式的值为:
Minute: [0-59, 90 (each minute)]
Hour: [0-23, 90 (each hour)]
Day of month: [1-31, 90 (each day of month), 91 (last day of month)]
Month: [1-12, 90 (each month)]
Run Code Online (Sandbox Code Playgroud)
所以,例如我有这种格式:10 - 2 - 90 - 90转换为2015-07-16 2:10.确定下一个运行时间日期的方法能够向我显示该日期.但是,我正在寻找有效的方法来检查下一个运行时间日期是否已经过去(简单部分),然后再次生成第一个下一个运行时间日期.在这种情况下,它会2015-07-17 2:10.
我发现我们的大脑很容易完成任务,但我不确定要以最有效的方式确定这一步的逻辑步骤(没有写出所有可能性).
有什么建议?
ala*_*agu 10
它工作正常.我正在使用PHP Cron Parser.它拥有我们需要的一切.
否则,您可以更轻松,更高效地使用Cron Expression.一些参考答案已经在这里和这里的堆栈溢出.
对于Cron Expression,您可以使用:
$cron = Cron\CronExpression::factory('@daily');
$cron->isDue();
echo $cron->getNextRunDate()->format('Y-m-d H:i:s');//this give next run date.
//echo $cron->getPreviousRunDate()->format('Y-m-d H:i:s');//this give previous run date.
Run Code Online (Sandbox Code Playgroud)
这和你所拥有的完全一样,Cron Expression也有,
您需要做的就是使用PHP Cron Expression.希望这可以帮助.
这几乎是Cron语法,那么为什么要创建一些完全相同的工作呢?
切换到有效的cron语法并使用简单的库进行解析等应该很容易.
一个例子是https://github.com/mtdowling/cron-expression,您可以免费获得下一个运行日期:
$cron->getNextRunDate()->format('Y-m-d H:i:s');
Run Code Online (Sandbox Code Playgroud)
您还可以使用0/15之类的值每15分钟运行一次等.另一个好处是,cron语法是常识,可以防止对格式的误解.
我假设这是每天的间隔.如果没有,你可以调整strtotime线.
您需要将日期转换为时间戳,然后在其上添加一天.PHP使这很容易.
假设您已将日期解析为国际格式2015-07-17 2:10,您可以执行以下操作:
$date = '2015-07-17 2:10'; // Parsed date
$timestamp = strtotime($date);
if($timestamp > time()){
// Date hasn't hit yet
} else {
$next_run = strtotime("+1 day", $timestamp);
}
Run Code Online (Sandbox Code Playgroud)
查看https://github.com/fightbulc/moment.php,它可以添加/减少秒,分,小时,月和年.例如(取自github演示站点):
$m = new \Moment\Moment('2012-05-15T12:30:00', 'CET');
echo $m->addHours(2)->format(); // 2012-05-15T14:30:00+0200
$m = new \Moment\Moment('2012-05-15T12:30:00', 'CET');
echo $m->subtractDays(7)->subtractMinutes(15)->format(); // 2012-05-08T12:15:00+0200
Run Code Online (Sandbox Code Playgroud)
为什么要担心它是否已经运行,或者它的下一个运行时间是什么时候?
你可以每分钟运行一个脚本,检查所有匹配的作业,然后执行它们吗?
写一个匹配某个时间点的所有可能性的SQL查询应该不是一个大问题:)
你可以简单地使用原生的DateTimeclasse.
$timeString = '2015-07-16 2:10';
$date = DateTime::createFromFormat('Y-m-d H:i', $timeString);
$date->modify('+1 day');
$now = new DateTime();
if ($date > $now) {
// The date is in the future
} else {
// The date is today, or is in the past
}
Run Code Online (Sandbox Code Playgroud)
但是如果你需要一个真正的cron语法,那么@echox的答案要好得多.
老实说,我对接受和奖励的答案不太满意,因为我想自己解决这个问题,而不是最终使用外部库并重写我的代码。
鉴于问题中描述的类似 cron 的语法,我创建了一个函数来确定下一次运行时间。我想分享它,希望将来如果您遇到类似问题时可以帮助其他人。也许它会为您指明您需要的方向。
一些演示案例
$cases = [
// Every minute
['i' => 90, 'H' => 90, 'd' => 90, 'm' => 90],
// Every 5th minute
['i' => 5, 'H' => 90, 'd' => 90, 'm' => 90],
// Every day at 02:15
['i' => 15, 'H' => 2, 'd' => 90, 'm' => 90],
// Every last day of the month at 15:20
['i' => 20, 'H' => 15, 'd' => 91, 'm' => 90],
// June 4th at 12:37
['i' => 37, 'H' => 12, 'd' => 4, 'm' => 6],
// Every minute between 04:00 and 05:00 at every day in October
['i' => 90, 'H' => 4, 'd' => 90, 'm' => 10],
];
Run Code Online (Sandbox Code Playgroud)
功能:
function getNextRunTime($config) {
$minute = $config['i'];
$hour = $config['H'];
$day = $config['d'];
$month = $config['m'];
// Get minute
switch($minute) {
case 90 :
$nextMinute = date('i', strtotime('now + 1 minute'));
break;
default :
$nextMinute = $minute;
}
// Get hour
switch($hour) {
case 90 :
if($minute == 90 || $nextMinute > date('i')) {
$nextHour = date('H');
} else {
$nextHour = date('H', strtotime('now + 1 hour'));
}
break;
default :
$nextHour = $hour;
}
// Get day
switch($day) {
case 90 :
if($hour == 90 && $nextHour > date('H')) {
$nextDay = date('d');
} elseif($hour <> 90 && $nextHour <= date('H')) {
$nextDay = date('d', strtotime('now + 1 day'));
} else {
if($nextHour > date('H')) {
$nextDay = date('d');
} else {
if ($nextMinute > date('i')) {
$nextDay = date('d');
} else {
$nextDay = date('d', strtotime('now + 1 day'));
}
}
}
break;
case 91 :
if(date('t') == date('d')) {
if($nextHour > date('H')) {
$nextDay = date('d');
} elseif($nextHour == date('H') && $nextMinute > date('i')) {
$nextDay = date('d');
} else {
$nextDay = date('t', strtotime('now + 1 month'));
}
} else {
$nextDay = date('t');
}
break;
default :
$nextDay = $day;
}
// Get month
switch($month) {
case 90 :
if($day == 90 || $nextDay > date('d')) {
$nextMonth = date('m');
} elseif($nextDay == date('d')) {
if($hour == 90 || $nextHour > date('H')) {
$nextMonth = date('m');
} elseif($nextHour == date('H')) {
if($minute == 90 || $nextMinute > date('i')) {
$nextMonth = date('m');
} else {
$nextMonth = date('m', strtotime('now + 1 month'));
}
} else {
$nextMonth = date('m', strtotime('now + 1 month'));
}
} else {
$nextMonth = date('m', strtotime('now + 1 month'));
}
break;
default :
$nextMonth = $month;
}
// Get year
if($month == 90 || $nextMonth > date('m')) {
$nextYear = date('Y');
} elseif($nextMonth == date('m')) {
if($day == 90 || $nextDay > date('d')) {
$nextYear = date('Y');
} elseif($nextDay == date('m')) {
if($hour == 90 || $nextHour > date('H')) {
$nextYear = date('Y');
} elseif($nextHour == date('H')) {
if($minute == 90 || $nextMinute > date('i')) {
$nextYear = date('Y');
} else {
$nextYear = date('Y') + 1;
}
} else {
$nextYear = date('Y') + 1;
}
} else {
$nextYear = date('Y') + 1;
}
} else {
$nextYear = date('Y') + 1;
}
// Create the timestamp for the 'Next Run Time'
$nextRunTime = mktime($nextHour, $nextMinute, 0, $nextMonth, $nextDay, $nextYear);
// Check if the job has to run every minute, maybe a reset to d-m-Y h:00 is possible
if($nextRunTime > time() && $minute == 90) {
$tempNextRunTime = mktime($nextHour, 0, 0, $nextMonth, $nextDay, $nextYear);
if($tempNextRunTime > time()) {
$nextMinute = 0;
$nextRunTime = $tempNextRunTime;
}
}
// Check if the job has to run every hour, maybe a reset to d-m-Y 00:i is possible
if($nextRunTime > time() && $hour == 90) {
$tempNextRunTime = mktime(0, $nextMinute, 0, $nextMonth, $nextDay, $nextYear);
if($tempNextRunTime > time()) {
$nextHour = 0;
$nextRunTime = $tempNextRunTime;
}
}
// Check if the job has to run every day, maybe a reset to 1-m-Y H:i is possible
if($nextRunTime > time() && $day == 90) {
$tempNextRunTime = mktime($nextHour, $nextMinute, 0, $nextMonth, 1, $nextYear);
if($tempNextRunTime > time()) {
$nextRunTime = $tempNextRunTime;
}
}
// Return the Next Run Time timestamp
return $nextRunTime;
}
Run Code Online (Sandbox Code Playgroud)
输出(执行时间2015年9月23日11:12):
string '23-09-2015, 11:13' (length=17)
string '23-09-2015, 12:05' (length=17)
string '24-09-2015, 02:15' (length=17)
string '30-09-2015, 15:20' (length=17)
string '04-06-2016, 12:37' (length=17)
string '01-10-2015, 04:00' (length=17)
Run Code Online (Sandbox Code Playgroud)