nächsten lauf eines cronjobs berechnen

Alles, was PHP betrifft, kann hier besprochen werden.

nächsten lauf eines cronjobs berechnen

Postby dunst0 » 31. March 2009 00:48

Ich möchte aus einem Array der die Angaben über ein Cronjob enthält den nächsten lauf des Cronjobs ausrechnen, also als timestamp.

zb so einer...

Code: Select all

$cron 
= array('weekday'   =>   '*',
              'month'     =>  '1-8,10-12/2',
              'day'       =>  '*',
              'hour'      =>  '*',
              'minute'    =>  '*/5');
 


das Script soll dann von der jetzigen zeit aus den nächsten lauf des cronjobs errechnen
wichtig ist mir dabei das alle im crontab erlaubten angaben möglich sein sollen

ich hab da schon ewig probiert bin aber immer wieder wohl zu kompliziert ran gegangen. :cry:

Vielleicht hat jemand von euch eine idee, wie es am saubersten umgesezt werden könnte.

//EDIT:

Hier mal meine weiterer versuch.

Code: Select all
<?PHP

/******************************************
*                                         *
*   Autor       :   Rick Barenthin        *
*   Email       :   dunst0@gmail.com      *
*                                         *
*   Copyright   :   2008                  *
*   Licence     :   GPL                   *
*                                         *
*******************************************/




class cron {
 
  var $t = 0;
  var $cron_now = array ();
 
 
  /// <summary>
  /// Constructor der Klasse, legt den Bezugs Timestamp fest und zerlegt ihn.
  /// </summary>
  function __construct () {
   
    $this->t = time ( );
    $this->cron_now = array('weekday'   =>  (int)date('N', $this->t),
                            'day'       =>  (int)date('j', $this->t),
                            'month'     =>  (int)date('n', $this->t),
                            'hour'      =>  (int)date('G', $this->t),
                            'minute'    =>  (int)date('i', $this->t),
                            'year'      =>  (int)date('Y', $this->t));
   
  }
 
 
  /// <summary>
  /// Erstellt ein Array mit dem im Cron Datums String enhaltenen Angaben.
  /// </summary>
  /// <param name="date_string">
  ///   string date_string
  /// </param>
  /// <param name="start">
  ///   int start
  /// </param>
  /// <param name="ende">
  ///   int ende
  /// </param>
  /// <returns>array do_when enth&auml;lt die Zeitpunkte aus dem Cron Datums String</returns>
  function check_date_string ($date_string, $start, $ende) {
 
    $liste = explode ( ',', $date_string );
    $anzahl = count ( $liste );
    $do_when = array ( );
   
    $c = 0;
   
    do
    {
      $r = explode ( '/', $liste[$c]);
      $steps = ( $r[1] != null ? $r[1] : 1 );
      $liste[$c] = $r[0];
     
      if ( strpos( $liste[$c], '-') !== false )
      {
        $bereich = explode ( '-', $liste[$c] );
       
        $i = $bereich[0] > $start ? $bereich[0] : $start;
       
        do
        {
          $do_when[] = $i;
          $i += $steps;
       
        } while ( $i <= $bereich[1] );
       
      }
      else if ( strpos( $liste[$c], '*') !== false )
      {
        $i = $start;
       
        do
        {
          $do_when[] = $i;
          $i += $steps;
       
        } while ( $i <= $ende );
       
      }
      else if ( $liste[$c] != '' )
      {
        $do_when[] = $liste[$c];
      }
     
      $c++;
    } while ( $c <= $anzahl );
   
    return $do_when;
 
  }
 
 
  /// <summary>
  /// Berechnet den n&auml;chsten Ausf&uuml;hrungs-Zeitpunkt eines Cronjobs.
  /// </summary>
  /// <param name="cronjob">
  ///   array ('weekday' => weekday,
  ///          'day' => day,
  ///          'month' => month,
  ///          'hour' => hour,
  ///          'minute' => minute)
  /// </param>
  /// <returns>timestamp des n&auml;chsten Ausf&uuml;hrungs-Zeitpunktes</returns>
  function calculate_next_run ( $cronjob ) {
 
    $WEEKDAY = array ( );
    $MONTH = array ( );
    $DAY = array ( );
    $HOUR = array ( );
    $MINUTE = array ( );
   
    $WEEKDAY = $this->check_date_string ( $cronjob['weekday'], 1, 7 );
    $MONTH = $this->check_date_string ( $cronjob['month'], 1, 12 );
    $HOUR = $this->check_date_string ( $cronjob['hour'], 0, 23 );
    $MINUTE = $this->check_date_string ( $cronjob['minute'], 0, 59 );
   
    $c1 = 0;
    $next_run = null;
    $anzahl1 = count ( $MONTH );
   
    do
    {
      $days_in_month = date( 't', mktime ( 0, 0, 0, $MONTH[$c1], 1, $this->cron_now['year'] ) );
      $DAY = $this->check_date_string ( $cronjob['day'], 1, $days_in_month );
     
      $c2 = 0;
      $anzahl2 = count ( $DAY );
     
      do
      {
        $c3 = 0;
        $anzahl3 = count ( $WEEKDAY );
       
        do
        {
          $day2weekday = date ( 'N', mktime ( 0, 0, 0, $MONTH[$c1], $DAY[$c2], $this->cron_now['year'] ) );
         
          if ( $WEEKDAY[$c3] == $day2weekday )
          {
         
            if ( $MONTH[$c1] == $this->cron_now['month'] && $DAY[$c2] >= $this->cron_now['day'] )
            {
              $c4 = 0;
              $anzahl4 = count ( $HOUR );
             
              do
              {
             
                if ( $HOUR[$c4] == $this->cron_now['hour'] ) {
               
                  $c5 = 0;
                  $anzahl5 = count ( $MINUTE );
                 
                  do
                  {
                    if ( $MINUTE[$c5] > $this->cron_now['minute'] )
                    {
                      $next_run = mktime ( $HOUR[$c4], $MINUTE[$c5], 0, $MONTH[$c1], $DAY[$c2], $this->cron_now['year'] );
                    }
                   
                    $c5++;
                  } while ( $c5 < $anzahl5 && $next_run == null );
               
                }
                elseif ( $HOUR[$c4] > $this->cron_now['hour'] ) {
               
                  $c5 = 0;
                  $anzahl5 = count ( $MINUTE );
                 
                  do
                  {
                    $next_run = mktime ( $HOUR[$c4], $MINUTE[$c5], 0, $MONTH[$c1], $DAY[$c2], $this->cron_now['year'] );
                   
                    $c5++;
                  } while ( $c5 < $anzahl5 && $next_run == null );
               
                }
               
                $c4++;
              } while ( $c4 < $anzahl4 && $next_run == null );
            }
           
            elseif ( $MONTH[$c1] > $this->cron_now['month'])
            {
              $c4 = 0;
              $anzahl4 = count ( $HOUR );
             
              do
              {
             
                if ( $HOUR[$c4] == $this->cron_now['hour'] ) {
               
                  $c5 = 0;
                  $anzahl5 = count ( $MINUTE );
                 
                  do
                  {
                    if ( $MINUTE[$c5] > $this->cron_now['minute'] )
                    {
                      $next_run = mktime ( $HOUR[$c4], $MINUTE[$c5], 0, $MONTH[$c1], $DAY[$c2], $this->cron_now['year'] );
                    }
                   
                    $c5++;
                  } while ( $c5 < $anzahl5 && $next_run == null );
               
                }
                elseif ( $HOUR[$c4] > $this->cron_now['hour'] ) {
               
                  $c5 = 0;
                  $anzahl5 = count ( $MINUTE );
                 
                  do
                  {
                    $next_run = mktime ( $HOUR[$c4], $MINUTE[$c5], 0, $MONTH[$c1], $DAY[$c2], $this->cron_now['year'] );
                   
                    $c5++;
                  } while ( $c5 < $anzahl5 && $next_run == null );
               
                }
               
                $c4++;
              } while ( $c4 < $anzahl4 && $next_run == null );
            }
          }
         
          $c3++;
        } while ( $c3 < $anzahl3 && $next_run == null );
       
        $c2++;
      } while ( $c2 < $anzahl2 && $next_run == null );
     
      $c1++;
    } while ( $c1 < $anzahl1 && $next_run == null );
   
    return $next_run;

  }
 
}



$cron = new cron;


$cronjob = array('weekday'   =>  '*/1',
                  'month'     =>  '*',
                  'day'       =>  '*',
                  'hour'      =>  '*',
                  'minute'    =>  '1-59/2');


echo date('r', $cron->t) .'<br>';
echo date('r', $cron->calculate_next_run($cronjob));

?>


Den nächsten Ausführungstermin scheint dieses Script schon mal zu berechnen.
Nur bin ich mir nicht sicher ob es programmier technisch so sauber ist.
Und ob man es nicht effizienter programmieren könnte. :oops:

//EDIT2: irgendwie klappt das beim letzten source code nicht mit dem syntax highlighting nicht so ganz schade

//EDIT3: leider geht das so nicht wenn es der 31.12. ist und der nächste Termin im nächsten Jahr liegt.

Grüße,
dunst
dunst0
 
Posts: 2
Joined: 31. March 2009 00:31

Re: nächsten lauf eines cronjobs berechnen

Postby dunst0 » 03. April 2009 13:48

So nach etwas weiter probieren kam, folgendes heraus.
Ich würde mich freuen über Berichtigungen und Verbesserungen des Codes.
Falls jemand eine Idee hat wie es besser gelöst werden kann, ich wäre über jede Hilfe dankbar. :D


Code: Select all
<?PHP

/******************************************
*                                         *
*   Autor       :   Rick Barenthin        *
*   Email       :   dunst0@gmail.com      *
*                                         *
*   Copyright   :   2008                  *
*   Licence     :   GPL                   *
*                                         *
*******************************************/




class cron {
 
  private $t = 0;
  private $cron_now = array ();
 
 
  /// <summary>
  /// Constructor der Klasse, legt den Bezugs Timestamp fest und zerlegt ihn.
  /// </summary>
  public function __construct () {
   
    $this->t = time ( );
    $this->cron_now = array('weekday'   =>  (int)date('N', $this->t),
                            'day'       =>  (int)date('j', $this->t),
                            'month'     =>  (int)date('n', $this->t),
                            'hour'      =>  (int)date('G', $this->t),
                            'minute'    =>  (int)date('i', $this->t),
                            'year'      =>  (int)date('Y', $this->t));
   
  }
 
 
  /// <summary>
  /// Erstellt ein Array mit dem im Cron Datums String enhaltenen Angaben.
  /// </summary>
  /// <param name="date_string">
  ///   string date_string
  /// </param>
  /// <param name="start">
  ///   int start
  /// </param>
  /// <param name="ende">
  ///   int ende
  /// </param>
  /// <returns>array do_when enth&auml;lt die Zeitpunkte aus dem Cron Datums String</returns>
  private function check_date_string ($date_string, $start, $ende) {
 
    $liste = explode ( ',', $date_string );
    $anzahl = count ( $liste );
    $do_when = array ( );
   
    $c = 0;
   
    do
    {
      $r = explode ( '/', $liste[$c]);
      $steps = ( $r[1] != null ? $r[1] : 1 );
      $liste[$c] = $r[0];
     
      if ( strpos( $liste[$c], '-') !== false )
      {
        $bereich = explode ( '-', $liste[$c] );
       
        $i = $bereich[0] > $start ? $bereich[0] : $start;
       
        do
        {
          $do_when[] = $i;
          $i += $steps;
       
        } while ( $i <= $bereich[1] );
       
      }
      else if ( strpos( $liste[$c], '*') !== false )
      {
        $i = $start;
       
        do
        {
          $do_when[] = $i;
          $i += $steps;
       
        } while ( $i <= $ende );
       
      }
      else if ( $liste[$c] != '' )
      {
        $do_when[] = $liste[$c];
      }
     
      $c++;
    } while ( $c <= $anzahl );
   
    return $do_when;
 
  }
 
 
  /// <summary>
  /// Berechnet den n&auml;chsten Ausf&uuml;hrungs-Zeitpunkt eines Cronjobs.
  /// </summary>
  /// <param name="cronjob">
  ///   array ('weekday' => weekday,
  ///          'day' => day,
  ///          'month' => month,
  ///          'hour' => hour,
  ///          'minute' => minute)
  /// </param>
  /// <returns>timestamp des n&auml;chsten Ausf&uuml;hrungs-Zeitpunktes</returns>
  public function calculate_next_run ( $cronjob ) {
   
    $WEEKDAY = array ( );
    $MONTH = array ( );
    $DAY = array ( );
    $HOUR = array ( );
    $MINUTE = array ( );
    $YEAR = array ( $this->cron_now['year'], $this->cron_now['year']+1 );
   
   
    $next_run = null;
   
    $WEEKDAY = $this->check_date_string ( $cronjob['weekday'], 1, 7 );
    $MONTH = $this->check_date_string ( $cronjob['month'], 1, 12 );
    $HOUR = $this->check_date_string ( $cronjob['hour'], 0, 23 );
    $MINUTE = $this->check_date_string ( $cronjob['minute'], 0, 59 );
   
    $c = 0;
    $anzahl = count ( $YEAR );
   
    do
    {
     
      $c1 = 0;
      $anzahl1 = count ( $MONTH );
     
      do
      {
        $days_in_month = date( 't', mktime ( 0, 0, 0, $MONTH[$c1], 1, $YEAR[$c] ) );
        $DAY = $this->check_date_string ( $cronjob['day'], 1, $days_in_month );
       
        $c2 = 0;
        $anzahl2 = count ( $DAY );
       
        do
        {
          $c3 = 0;
          $anzahl3 = count ( $WEEKDAY );
         
          do
          {
            $day2weekday = date ( 'N', mktime ( 0, 0, 0, $MONTH[$c1], $DAY[$c2], $YEAR[$c] ) );
           
            if ( $WEEKDAY[$c3] == $day2weekday )
            {
             
              if ( $YEAR[$c] == $this->cron_now['year'] )
              {
             
                if ( $MONTH[$c1] == $this->cron_now['month'] && $DAY[$c2] >= $this->cron_now['day'] )
                {
                 
                  if ( $DAY[$c2] == $this->cron_now['day'] ) {
                 
                    $c4 = 0;
                    $anzahl4 = count ( $HOUR );
                   
                    do
                    {
                   
                      if ( $HOUR[$c4] == $this->cron_now['hour'] ) {
                     
                        $c5 = 0;
                        $anzahl5 = count ( $MINUTE );
                       
                        do
                        {
                          if ( $MINUTE[$c5] > $this->cron_now['minute'] )
                          {
                            $next_run = mktime ( $HOUR[$c4], $MINUTE[$c5], 0, $MONTH[$c1], $DAY[$c2], $YEAR[$c] );
                          }
                         
                          $c5++;
                        } while ( $c5 < $anzahl5 && $next_run == null );
                     
                      }
                      elseif ( $HOUR[$c4] > $this->cron_now['hour'] ) {
                     
                        $c5 = 0;
                        $anzahl5 = count ( $MINUTE );
                       
                        do
                        {
                          $next_run = mktime ( $HOUR[$c4], $MINUTE[$c5], 0, $MONTH[$c1], $DAY[$c2], $YEAR[$c] );
                         
                          $c5++;
                        } while ( $c5 < $anzahl5 && $next_run == null );
                     
                      }
                     
                      $c4++;
                    } while ( $c4 < $anzahl4 && $next_run == null );
                   
                  }
                 
                  elseif ( $DAY[$c2] > $this->cron_now['day'] ) {
                 
                    $c4 = 0;
                    $anzahl4 = count ( $HOUR );
                   
                    do
                    {
                   
                        $c5 = 0;
                        $anzahl5 = count ( $MINUTE );
                       
                        do
                        {
                          $next_run = mktime ( $HOUR[$c4], $MINUTE[$c5], 0, $MONTH[$c1], $DAY[$c2], $YEAR[$c] );
                         
                          $c5++;
                        } while ( $c5 < $anzahl5 && $next_run == null );
                     
                      $c4++;
                    } while ( $c4 < $anzahl4 && $next_run == null );
                   
                  }
                 
                }
               
                elseif ( $MONTH[$c1] > $this->cron_now['month'])
                {
                  $c4 = 0;
                  $anzahl4 = count ( $HOUR );
                 
                  do
                  {
                 
                    if ( $HOUR[$c4] == $this->cron_now['hour'] ) {
                   
                      $c5 = 0;
                      $anzahl5 = count ( $MINUTE );
                     
                      do
                      {
                        if ( $MINUTE[$c5] > $this->cron_now['minute'] )
                        {
                          $next_run = mktime ( $HOUR[$c4], $MINUTE[$c5], 0, $MONTH[$c1], $DAY[$c2], $YEAR[$c] );
                        }
                       
                        $c5++;
                      } while ( $c5 < $anzahl5 && $next_run == null );
                   
                    }
                    elseif ( $HOUR[$c4] > $this->cron_now['hour'] ) {
                   
                      $c5 = 0;
                      $anzahl5 = count ( $MINUTE );
                     
                      do
                      {
                        $next_run = mktime ( $HOUR[$c4], $MINUTE[$c5], 0, $MONTH[$c1], $DAY[$c2], $YEAR[$c] );
                       
                        $c5++;
                      } while ( $c5 < $anzahl5 && $next_run == null );
                   
                    }
                   
                    $c4++;
                  } while ( $c4 < $anzahl4 && $next_run == null );
                }
             
              }
              elseif ( $YEAR[$c] > $this->cron_now['year'] )
              {
             
                $c4 = 0;
                $anzahl4 = count ( $HOUR );
               
                do
                {
                   
                    $c5 = 0;
                    $anzahl5 = count ( $MINUTE );
                   
                    do
                    {
                      $next_run = mktime ( $HOUR[$c4], $MINUTE[$c5], 0, $MONTH[$c1], $DAY[$c2], $YEAR[$c] );
                     
                      $c5++;
                    } while ( $c5 < $anzahl5 && $next_run == null );
                 
                  $c4++;
                } while ( $c4 < $anzahl4 && $next_run == null );
             
              }
             
            }
           
            $c3++;
          } while ( $c3 < $anzahl3 && $next_run == null );
         
          $c2++;
        } while ( $c2 < $anzahl2 && $next_run == null );
       
        $c1++;
      } while ( $c1 < $anzahl1 && $next_run == null );
     
      $c++;
    } while ( $c < $anzahl && $next_run == null );
   
   
    return $next_run;
   
  }
 
}



$cron = new cron;


$cronjob = array('weekday'   =>  '*/3',
                  'month'     =>  '*',
                  'day'       =>  '*/6',
                  'hour'      =>  '10-15/2',
                  'minute'    =>  '1-59/2');

echo date('r', $cron->calculate_next_run($cronjob));

?>
dunst0
 
Posts: 2
Joined: 31. March 2009 00:31


Return to PHP

Who is online

Users browsing this forum: No registered users and 8 guests

cron