在PHP中计算cron下一个运行时 [英] Calculating cron next-run-time in PHP

查看:180
本文介绍了在PHP中计算cron下一个运行时的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在我自己的个人框架中设计一个任务调度程序,并试图避免不灵活的每隔分钟/小时/天运行方法,实行。我想做的是模仿cron调度。我有功能分配模式和计算下一个日期(月的天)目前,但不想继续推进,如果有一些比我做的更容易,或者可能更好的方法来做我想做的事情。

I'm designing a task scheduler in my own personal framework and am trying to avoid the not-as-flexible "run every n minutes/hours/days" method that'd be easier to implement. What I'd like to do is mimic cron scheduling. I've got functions in place to split patterns and calculate the next value for the next date (day of month) currently, but don't want to keep pushing forward if there's something easier than what I'm doing, or possibly a better way to do what I'm trying to do.

/**
  * Takes pattern(s) for various time attributes and calculates the next time the task should run
  *
  * @param mixed $minute Pattern or value of minute: 0-59 or 15,45 or * or * /5 (every 5 minutes)
  * @param mixed $hour Pattern or value of hour: 0-23 or 0,6,12 or * or * /2 (every 2 hours)
  * @param mixed $date Pattern or value of date: 1-31 or 1,15 or * or * /5 (every 5 days)
  * @param mixed $day Pattern or value of weekday: 0-7 or 0,1,7 or * or * /7 (every 7 days) - takes precedence over date
  * @return string Timestamp of next run time
  */
 public static function calcNextRun( $minute, $hour, $date, $day )
 {
  # Simplest first, if all * then we run every minute. Return timestamp for next whole minute
  if ( $minute == '*' && $hour == '*' && $date == '*' && $day == '*' )
   return mktime( date( "H" ), date( "i" ), 0 ) + 60; # Prettier than time() + 60, isn't that reason enough?

  # Default to current values
  $nextDate = date( "d" );
  $nextMonth = date( "m" );
  $nextYear = date( "Y" );
  $nextDay = date( "N" );
  $nextHour = date( "H" );
  $nextMinute = date( "i" );

  # Calculate month date to run on, using multiple dates in the presence of , or -
  if( strstr( $date, ',' ) || strstr( $date, '-' ) )
  {
   # Variable to determine whether the date has been set or not
   $dateSet = false;

   # Determine if there's a range in thurr
   $rangeExists = ( strstr( $date, '-' ) ) ? true : false ;

   # Set up the $dates array, exploding if multiple values is present
   $dates = array();
   if ( strstr( $date, ',' ) )
    $dates = explode( ',', $date );
   else
    $dates[] = $date;

   # If we have a range(s) present then we expand them into full stuffs
   foreach ( $dates as $key => $val )
    if ( strstr( $val, '-' ) )
     $dates = array_merge( $dates, self::expandRange( $val ) ); # Merge the expanded range into the $dates array

   # Loop through the $dates array and remove any lingering ranges
   foreach ( $dates as $key => $val )
    if ( strstr( $val, '-' ) )
     unset( $dates[ $key ] );

   # Sort the array
   sort( $dates );

   # Determine the next lowest value
   foreach( $dates as $val )
   {
    # If the value is higher than the maximum number of dates this month, lower it to that
    if ( $val > date( "t" ) )
     $val = date( "t" );

    # If $val is higher than today's date, we use that
    if ( $val > date( "d" ) )
    {
     $nextDate = $val;
     $dateSet = true;
     break; # We're done, we have our value
    }
   }

   # If the date has not been set, add one to the month and use the lowest value in the array
   if ( !$dateSet )
   {
    # Increment the month. Maybe the year. Hurr hurr
    if ( $nextMonth == 12 )
    {
     $nextMonth = 1;
     $nextYear++;
    }
    else
     $nextMonth++;

    # Set the next day to the lowest value in the array
    $nextDate = $dates[0];
   }
  }
  elseif ( strstr( $date, '/' ) ) # Every n days
  {
   $parts = explode( '/', $date );
   $numDays = array_pop( $parts );

   # Calculate the timestamp of n days from now
   $nDayTime = time() + ( $numDays * 86400 ); # 86400 seconds in a day

   # Update values of $nextVars
   $nextDate = date( "d", $nDayTime );
   $nextMonth = date( "m", $nDayTime );
   $nextYear = date( "Y", $nDayTime );
   $nextDay = date( "N", $nDayTime );
  }
  elseif ( $date == (int)$date )
  {
   if ( $date < date( "j" ) )
   {
    # Determine if the month pushes into the next year
    if ( $nextMonth == 12 )
    {
     $nextMonth = 1;
     $nextYear++;
    }
    else
     $nextMonth++;
   }

   $nextDate = $date;
  }

  # Return the new timestamp!
  return mktime( $nextHour, $nextMinute, 0, $nextMonth, $nextDate, $nextYear );
 }

 /**
  * Takes a range and returns an array with all values belonging to that range
  *
  * @param string $range Two values split by a hyphen, ie: 1-5, 0-9, etc.
  * @return array Array of values between the two parts of the range
  */
 private static function expandRange( $range )
 {
  # Get the parts of the range
  $range = explode( '-', $range );

  # Sort just in case the range is handed to us backwards. <_<
  sort( $range );

  # Set up our return array
  $returnArray = array();

  # Populate the return array with all values between min and max
  for($i=$range[0];$i<=$range[1];$i++)
   $returnArray[] = $i;

  return $returnArray;
 }



我不介意使用cron使用的所有五个参数,任何一种方式,我想能够轻松计算匹配提供的模式的下一个时间戳。

I don't mind using all five of the parameters that cron uses, but either way I want to be able to easily calculate the next timestamp that matches the pattern provided.

有没有人有任何建议完成这个?我想创建一个函数,它将采取模式(1-7,10,15或* / 5或*或任何)和当前val(当前分钟,一个月的某天),并返回下一个值

Does anyone have any recommendations for accomplishing this? I'm thinking of creating a function that will take a pattern (1-7,10,15 or */5 or * or whatever) and a current val (the current minute, day of month, whatever) and return the next value from that pattern that either matches or is higher than the current value.

推荐答案

我为PHP创建了一个CRON解析器,可以处理您的调度需求。它支持范围增量(3-59 / 12,* / 2),范围(3-5),散列(3#2),一个月/月最后一天的最后一个工作日(5L,L)工作日到一个指定的日期(15W),以及可选的年份字段。

I created a CRON parser for PHP that can handle your scheduling needs. It supports everything including increments of ranges (3-59/12, */2), ranges (3-5), hashes (3#2), last weekday in a month/last day of month (5L, L), nearest weekday to a given day of the month (15W), and an optional year field.

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

用法:

<?php

// Works with predefined scheduling definitions
$cron = Cron\CronExpression::factory('@daily');
$cron->isDue();
$cron->getNextRunDate();
$cron->getPreviousRunDate();

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

计算下次执行cron作业时的时间

这篇关于在PHP中计算cron下一个运行时的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆