2011-01-03 8 views
14

Ho bisogno di sviluppare un sistema di attività che dovrebbe essere in grado di funzionare su server che non supportano crontab.Funzione PHP che riceve una stringa di cron e restituisce la data/ora successiva

sto chiedendo se c'è qualche codice esistente che può prendere una stringa cron (ad esempio '0 0,12 1 */2 *' e riprendere il timestamp della successiva esecuzione pianificata.

Se un tale il codice non è stato trovato allora come dovrei iniziare con quella

+0

http://stackoverflow.com/questions/321494/calculate-when-a-cron-job-will-be-executed-then-next-time/3453872#3453872 –

risposta

12

si potrebbe usare questa classe PHP-Parse-cron-strings-and-compute-schedules

sarà anche calcolare l'ultima programmata corsa

+3

vedere anche http: // stackoverflow.it/questions/321494/calculate-when-a-cron-job-will-be-execut-then-next-time – berebidahoo

+0

Io uso la classe cron PHP-Parse per eseguire sub-crons su due server e non ho avuto un singolo problema con esso – Patrick

8

usare questa funzione:?

function parse_crontab($time, $crontab) 
     {$time=explode(' ', date('i G j n w', strtotime($time))); 
      $crontab=explode(' ', $crontab); 
      foreach ($crontab as $k=>&$v) 
        {$time[$k]=intval($time[$k]); 
        $v=explode(',', $v); 
        foreach ($v as &$v1) 
          {$v1=preg_replace(array('/^\*$/', '/^\d+$/', '/^(\d+)\-(\d+)$/', '/^\*\/(\d+)$/'), 
              array('true', $time[$k].'===\0', '(\1<='.$time[$k].' and '.$time[$k].'<=\2)', $time[$k].'%\1===0'), 
              $v1 
              ); 
          } 
        $v='('.implode(' or ', $v).')'; 
        } 
      $crontab=implode(' and ', $crontab); 
      return eval('return '.$crontab.';'); 
     } 
var_export(parse_crontab('2011-05-04 02:08:03', '*/2,3-5,9 2 3-5 */2 *')); 
var_export(parse_crontab('2011-05-04 02:08:03', '*/8 */2 */4 */5 *')); 
+0

funzione impressionante. Qui è con uno stile di codice più standard. https://gist.github.com/goosehub/7deff7928be04ec99b4292be10b4b7b0 – Goose

+0

Ho trovato un bug nel codice. Vedi la mia risposta per la spiegazione e sentiti libero di applicarla alla tua risposta. – Goose

+0

@Goose, penso che "$ time [$ k] = intval ($ time [$ k]);" è ok – diyism

0

Nella funzione parse_crontab:

Sostituire $time[$k] con intval($time[$k]) all'interno del preg_replace linea
per confrontare due base10 numeri correttamente.

+0

Puoi per favore riformulare la tua risposta? È difficile da capire. C'è una funzione parse_crontab disponibile? Dove? Come? E cos'è la sostituzione del codice? Stai suggerendo di adattare la funzione 'parse_crontab'? – einpoklum

1

Ho trovato che il diyismo ha avuto un'ottima risposta, ma ha trovato un bug cruciale.

Se si immette un tempo cron come 0 * * * *, verrà eseguito a 0 minuti, 8, minuti e 9 minuti. Il codice fornisce un condizionale 08===0, che restituisce true, perché PHP interpreta i numeri che iniziano con 0 come ottale, e 08 e 09 non sono numeri ottali validi, quindi vengono interpretati come 0. Altre informazioni qui.

How to prevent PHP from doing octal math in conditionals? (why does 08 === 0)

Ecco una versione fissa e ben commentato di codice di diyism.

// Parse CRON frequency 
function parse_crontab($time, $crontab) { 
    // Get current minute, hour, day, month, weekday 
    $time = explode(' ', date('i G j n w', strtotime($time))); 
    // Split crontab by space 
    $crontab = explode(' ', $crontab); 
    // Foreach part of crontab 
    foreach ($crontab as $k => &$v) { 
     // Remove leading zeros to prevent octal comparison, but not if number is already 1 digit 
     $time[$k] = preg_replace('/^0+(?=\d)/', '', $time[$k]); 
     // 5,10,15 each treated as seperate parts 
     $v = explode(',', $v); 
     // Foreach part we now have 
     foreach ($v as &$v1) { 
      // Do preg_replace with regular expression to create evaluations from crontab 
      $v1 = preg_replace(
       // Regex 
       array(
        // * 
        '/^\*$/', 
        // 5 
        '/^\d+$/', 
        // 5-10 
        '/^(\d+)\-(\d+)$/', 
        // */5 
        '/^\*\/(\d+)$/' 
       ), 
       // Evaluations 
       // trim leading 0 to prevent octal comparison 
       array(
        // * is always true 
        'true', 
        // Check if it is currently that time, 
        $time[$k] . '===\0', 
        // Find if more than or equal lowest and lower or equal than highest 
        '(\1<=' . $time[$k] . ' and ' . $time[$k] . '<=\2)', 
        // Use modulus to find if true 
        $time[$k] . '%\1===0' 
       ), 
       // Subject we are working with 
       $v1 
      ); 
     } 
     // Join 5,10,15 with `or` conditional 
     $v = '(' . implode(' or ', $v) . ')'; 
    } 
    // Require each part is true with `and` conditional 
    $crontab = implode(' and ', $crontab); 
    // Evaluate total condition to find if true 
    return eval('return ' . $crontab . ';'); 
} 
+0

Penso che "$ time [$ k] = intval ($ time [$ k]);" è ok, ho aggiornato la mia risposta, grazie. – diyism

+0

@diyism 'echo intval (09);' fornisce 0, quindi sfortunatamente devi usare '$ time [$ k] = preg_replace ('/^0 + (? = \ D) /', '', $ tempo [$ k]); ' – Goose

0

ho scritto una molto potente classe PHP chiamato CalendarEvent molto tempo fa:

https://github.com/cubiclesoft/php-misc/

Supporta due differenti sintassi del modello. Il cron normale non è in grado di gestire determinati pattern complessi, mentre la sintassi predefinita di CalendarEvent gestisce qualsiasi schema di pianificazione che potrebbe essere necessario. Il supporto per la sintassi del pattern cron è in realtà un fallback (prefondi le linee cron con cron e uno spazio).

CalendarEvent è stato scritto principalmente come una classe di calcolo degli eventi del calendario e si è appena verificato il supporto dei meccanismi di "prossimo trigger" in stile cron. In realtà è progettato per calcolare un'intera pianificazione per più mesi allo scopo di visualizzare un calendario per un utente (da cui il nome della classe). Ho anche usato la classe come soluzione intermedia per tradurre eventi tra piattaforme del calendario. Questo è lo scenario più raro - l'ho usato più frequentemente per le soluzioni di tipo cron di AddSchedule()/NextTrigger().