ParseCrontab.php 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. <?php
  2. namespace common\components;
  3. use common\traits\ErrorTrait;
  4. /**
  5. * 解析定时任务
  6. * @Author bing
  7. * @DateTime 2021-10-11 18:14:42
  8. * @copyright: Copyright (c) 2020 广东七件事集团
  9. */
  10. class ParseCrontab
  11. {
  12. use ErrorTrait;
  13. /**
  14. * 解析crontab的定时格式,linux只支持到分钟/,这个类支持到秒
  15. *
  16. * @Author bing
  17. * @DateTime 2021-10-12 11:53:38
  18. * @copyright: Copyright (c) 2020 广东七件事集团
  19. * @param string $crontab_string
  20. * @param int $start_time
  21. * 0 1 2 3 4 5
  22. * * * * * * *
  23. * - - - - - -
  24. * | | | | | |
  25. * | | | | | +----- day of week (0 - 6) (Sunday=0)
  26. * | | | | +----- month (1 - 12)
  27. * | | | +------- day of month (1 - 31)
  28. * | | +--------- hour (0 - 23)
  29. * | +----------- min (0 - 59)
  30. * +------------- sec (0-59)
  31. * @param int $start_time timestamp [default=current timestamp]
  32. * @throws InvalidArgumentException 错误信息
  33. * @return array|boolean
  34. */
  35. static public function parse($crontab_string, $start_time = null)
  36. {
  37. if (!preg_match('/^((\*(\/[0-9]+)?)|[0-9\-\,\/]+)\s+((\*(\/[0-9]+)?)|[0-9\-\,\/]+)\s+((\*(\/[0-9]+)?)|[0-9\-\,\/]+)\s+((\*(\/[0-9]+)?)|[0-9\-\,\/]+)\s+((\*(\/[0-9]+)?)|[0-9\-\,\/]+)\s+((\*(\/[0-9]+)?)|[0-9\-\,\/]+)$/i',
  38. trim($crontab_string))
  39. ) {
  40. if (!preg_match('/^((\*(\/[0-9]+)?)|[0-9\-\,\/]+)\s+((\*(\/[0-9]+)?)|[0-9\-\,\/]+)\s+((\*(\/[0-9]+)?)|[0-9\-\,\/]+)\s+((\*(\/[0-9]+)?)|[0-9\-\,\/]+)\s+((\*(\/[0-9]+)?)|[0-9\-\,\/]+)$/i',
  41. trim($crontab_string))
  42. ) {
  43. self::setStaticError("Invalid cron string: " . $crontab_string);
  44. return false;
  45. }
  46. }
  47. if ($start_time && !is_numeric($start_time)) {
  48. self::setStaticError("\$start_time must be a valid unix timestamp ($start_time given)");
  49. return false;
  50. }
  51. $cron = preg_split("/[\s]+/i", trim($crontab_string));
  52. $start = empty($start_time) ? time() : $start_time;
  53. if (count($cron) == 6) {
  54. $date = array(
  55. 'second' => (empty($cron[0])) ? array(0 => 0) : self::_parse_cron_number($cron[0], 0, 59),
  56. 'minutes' => self::_parse_cron_number($cron[1], 0, 59),
  57. 'hours' => self::_parse_cron_number($cron[2], 0, 23),
  58. 'day' => self::_parse_cron_number($cron[3], 1, 31),
  59. 'month' => self::_parse_cron_number($cron[4], 1, 12),
  60. 'week' => self::_parse_cron_number($cron[5], 0, 6),
  61. );
  62. } elseif (count($cron) == 5) {
  63. $date = array(
  64. 'second' => array(1 => 1),
  65. 'minutes' => self::_parse_cron_number($cron[0], 0, 59),
  66. 'hours' => self::_parse_cron_number($cron[1], 0, 23),
  67. 'day' => self::_parse_cron_number($cron[2], 1, 31),
  68. 'month' => self::_parse_cron_number($cron[3], 1, 12),
  69. 'week' => self::_parse_cron_number($cron[4], 0, 6),
  70. );
  71. }
  72. if (
  73. in_array(intval(date('i', $start)), $date['minutes']) &&
  74. in_array(intval(date('G', $start)), $date['hours']) &&
  75. in_array(intval(date('j', $start)), $date['day']) &&
  76. in_array(intval(date('w', $start)), $date['week']) &&
  77. in_array(intval(date('n', $start)), $date['month'])
  78. ) {
  79. return $date['second'];
  80. }
  81. return null;
  82. }
  83. /**
  84. * 解析单个配置的含义
  85. * @param $s
  86. * @param $min
  87. * @param $max
  88. * @return array
  89. */
  90. static protected function _parse_cron_number($s, $min, $max)
  91. {
  92. $result = array();
  93. $v1 = explode(",", $s);
  94. foreach ($v1 as $v2) {
  95. $v3 = explode("/", $v2);
  96. $step = empty($v3[1]) ? 1 : $v3[1];
  97. $v4 = explode("-", $v3[0]);
  98. $_min = count($v4) == 2 ? $v4[0] : ($v3[0] == "*" ? $min : $v3[0]);
  99. $_max = count($v4) == 2 ? $v4[1] : ($v3[0] == "*" ? $max : $v3[0]);
  100. for ($i = $_min; $i <= $_max; $i += $step) {
  101. if (intval($i) < $min) {
  102. $result[$min] = $min;
  103. } elseif (intval($i) > $max) {
  104. $result[$max] = $max;
  105. } else {
  106. $result[$i] = intval($i);
  107. }
  108. }
  109. }
  110. ksort($result);
  111. return $result;
  112. }
  113. }