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.
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ä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ächsten Ausführungs-Zeitpunkt eines Cronjobs.
/// </summary>
/// <param name="cronjob">
/// array ('weekday' => weekday,
/// 'day' => day,
/// 'month' => month,
/// 'hour' => hour,
/// 'minute' => minute)
/// </param>
/// <returns>timestamp des nächsten Ausfü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.
//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