【问题标题】:PHP - Get date of next crontab's runPHP - 获取下一个 crontab 运行的日期
【发布时间】:2018-04-19 18:53:52
【问题描述】:

我想从给定字符串(如 Cron Formatseconds 参数(不完全等于 cron 格式)中获取运行 cron 的下一个日期

我的代码:

$cron_format = explode(" ", "00 00 00 01 * *"); // <second> <minute> <hour> <day> <month> <week_day>
$date_diff   = explode(" ", "s i H d m w");     // php Date @link http://php.net/manual/en/function.date.php
$format = [];

foreach( $date_diff as $key=>$value) {
    $format[$value] = $cron_format[$key] !== "*" ? date($value, strtotime($cron_format[$key])) : date($value);
}

$spf = sprintf(
"%s-%s-%s %s:%s:%s", 
date("Y"), $format["m"], $format["d"], $format["H"], $format["i"], $format["s"]
);

$date = DateTime::createFromFormat("Y-m-d H:i:s", $spf);

// returns 2018-03-01 00:00:00, expected was 2018-04-01 00:00:00
echo $date->format("Y-m-d H:i:s"); 

Fiddle

它按预期读取2018-03-01 00:00:00,但我正在寻找的是一种获取下一个 Crontab 运行日期(2018-04-01 00:00:00) 的方法。

设置添加月份的方式并不能解决问题,因为 cron 格式 可以每小时设置一次,如:

<second> <minute> <hour> <day> <month> <week_day>
   00       00      *      *      *         *

【问题讨论】:

  • cron 作业的执行是否被记录在任何地方(日志文件等)?
  • @SpacePhoenix nop,但为什么呢?
  • @fiskolin,你有机会检查我发布的链接中的代码吗?
  • cron 表达式比您想象的要复杂得多。您需要使用库。不要成为英雄。

标签: php cron


【解决方案1】:

无需为此编写更多代码。请使用下面的库来做到这一点

https://github.com/mtdowling/cron-expression

用法:

<?php
// Works with cron expression
$cron = new Cron\CronExpression::factory('15 2,6-12 */15 1 *');
$cron->getNextRunDate();

【讨论】:

  • 谢谢,但我试图在不安装公共库的情况下达到相同的结果。
  • 为什么要@fiskolin?
  • 请注意,mtdowling repo 已被弃用,取而代之的是 dragonmantank repo:github.com/dragonmantank/cron-expression
【解决方案2】:

我玩了一点,这是我作为函数的结果。基本上我拆分元素,检查通配符的值。如果找到,它将忽略所有其他通配符并使用第一个通配符 +1 设置元素的值。此外,我检查 d 和 m 的零值,如果发现它们被值 1 替换。最后,我检查当前年份的日期是否小于当前日期。如果是,则使用当年,如果否,则使用下一年。

 function calculate_next_cronjob($cronjob, $elementpositions){

  $wildcard = false;
  $elements = preg_split('/[^\d*]+/', $cronjob);

  foreach(preg_split('/[^a-z]+/i', $elementpositions) as $key => $element){

    $value[$element] = $elements[$key];

    switch($element){
     case 's':
      if($value[$element] == '*'){
       $value[$element] = date('s') + 1;
       $wildcard = true;
      }
     break;
     case 'i':
      if($value[$element] == '*'){
       $value[$element] = date('i') + ($wildcard === true ? 0 : 1);
       $wildcard = true;
      }
     break;
     case 'H': 
      if($value[$element] == '*'){
       $value[$element] = date('H') + ($wildcard === true ? 0 : 1);
       $wildcard = true;
      }
     break;
     case 'd': 
      if($value[$element] == '*'){
       $value[$element] = date('d') + ($wildcard === true ? 0 : 1);
       $wildcard = true;
      }
      if(intval($value[$element]) == 0){
       $value[$element] = 1;          
      }
     break;
     case 'm': 
      if($value[$element] == '*'){
       $value[$element] = date('m') + ($wildcard === true ? 0 : 1);
       $wildcard = true;
      }
      if(intval($value[$element]) == 0){
       $value[$element] = 1; 
      }
     break;
      default:
      unset($value[$element]);
    }

  }

  $cy = date('Y');
  $ny = $cy + 1;

  if(time() < mktime($value['H'], $value['i'], $value['s'], $value['m'], $value['d'], $cy)){
   $value['Y'] = $cy;
  }else{
   $value['Y'] = $ny; 
  }

  return date('Y-m-d H:i:s', mktime($value['H'], $value['i'], $value['s'], $value['m'], $value['d'], $value['Y']));

 }  

测试运行:

 $cronjobs   = array();
 $cronjobs[] = array('00 00 00 00 *  00', 's  i  H  d m N');
 $cronjobs[] = array('00 00 00 *  *  00', 's  i  H  d m N');
 $cronjobs[] = array('00 00 *  *  *  00', 's  i  H  d m N');
 $cronjobs[] = array('00 *  *  *  *  00', 's  i  H  d m N');
 $cronjobs[] = array('*  *  *  *  *  00', 's  i  H  d m N');

 echo '<table>';
 foreach($cronjobs as $data){
  echo '<tr><td>';
  echo $data[0];
  echo '</td><td>';
  echo $data[1];
  echo '</td><td>';
  echo calculate_next_cronjob($data[0], $data[1]);
  echo '</td></tr>';
 }
 echo '</table>';

输出:

00 00 00 00 * 00 s i H d m N 2018-05-01 00:00:00 
00 00 00 *  * 00 s i H d m N 2018-04-17 00:00:00 
00 00 *  *  * 00 s i H d m N 2018-04-16 09:00:00 
00 *  *  *  * 00 s i H d m N 2018-04-16 08:25:00 
*  *  *  *  * 00 s i H d m N 2018-04-16 08:24:59 

【讨论】:

  • 太接近了。当给定00 00 05 * * *(可能是同一天的一个小时)时,它会返回明天的日期。
  • 我会努力解决的
猜你喜欢
  • 2012-12-11
  • 1970-01-01
  • 1970-01-01
  • 2011-09-06
  • 1970-01-01
  • 1970-01-01
  • 2016-03-24
  • 2010-12-10
  • 1970-01-01
相关资源
最近更新 更多