Ankündigung

Einklappen
Keine Ankündigung bisher.

Nächsten Zeitpunkt für crontab eintrag bestimmen

Einklappen

Neue Werbung 2019

Einklappen
X
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

  • Nächsten Zeitpunkt für crontab eintrag bestimmen

    Hi,
    die Cronsyntax ist ja ein alt bewährtes Mittel um Zeitpunkte für einmalige oder wiederkehrende Ereignisse zu definieren.
    Ich möchte ausgehend von einen Datum und einen String mit einer Crontab-Syntax wie z.B.
    PHP-Code:
    $cronStr "20,30 1 * * 1-5";  //mo-fr 01:20 und 1:30 
    den nächsten Zeitpunkt, welcher die Bedingung des cronStr entsprechend der üblichen Regeln (cron wiki) erfüllt, ermitteln.
    Beispiel:
    Es liegt ein Datum Sa, 22.7.2017 14:00 vor. Die Methode soll nun den nächsten Zeitpunkt ermitteln, der den Cron-Ausdruck "20,30 1 * * 1-5" erfüllt.
    Erwartetes Ergebnis: Mo, 24.07.2017 1:20

    Nun gibt es für PHP dafür schon zahlreiche Klassen. Diese sind mir jedoch zu mächtig und realisieren alle weit mehr als ich brauche.
    PHP-Frameworks kommen für meine Zielsysteme auch nicht in Frage.
    Meine erste Idee für eine Realisierung ist eine Schrittweise Erhöhung einzelner Datumsanteile (Monat, Tag..) mit einem Abgleich der Cronausdruckes bis es passt.
    Ich fürchte nur diese Variante wird sehr zeitaufwendig. Mir fehlt da noch sozusagen die zündende Idee.

    Gelöst ist bereits das Problem eine Zeit mit dem Cron-Ausdruck abzugleichen und damit auch das Parsen des Cronstrings.
    Konkret liefert eine Methode isCron() eines abgeleiteten DateTime-Objektes für ein String wie oben true oder false.

    Hat das jemand schon mit nativen PHP gelöst oder hat eine Idee dazu?

    LG jspit


  • #2
    Bon gerade mobil, fasse mich kurz.

    Ich nutze diese Lib dafür:

    https://github.com/mtdowling/cron-expression
    [URL="https://github.com/chrisandchris"]GitHub.com - ChrisAndChris[/URL] - [URL="https://github.com/chrisandchris/symfony-rowmapper"]RowMapper und QueryBuilder für MySQL-Datenbanken[/URL]

    Kommentar


    • #3
      Hab mir die Klasse mal auf eine Testplattform geladen. Erster Eindruck: Sehr gut!
      Noch überblickbar und unter PHP 7.1 und für meine Begriffe auch schnell. Konkret unter OS: Linux, PHP-Version: 7.1.7 (64 Bit) für das obige Beispiel unter 0,5ms.
      Da hab ich nur noch ein Problem: Muss das noch auf meinem Zielsystem unter PHP 5.6.x checken.

      Danke erstmal für den Link.

      LG jspit

      Kommentar


      • #4
        Nun das Problem ist einfacher zu lösen als ich Anfangs gedacht hatte. Ich hab mich dazu entschlossen, da neben anderen Gründen für die cron-expression Klasse PHP 7.0+ gefordert wird und ich nur PHP 5.6 für mein spezielles Zielsystem verfügbar habe.
        Damit kein falscher Eindruck entsteht, die Gründe das Problem selbst zu lösen sind ausschließlich meinem speziellen Anwendungsfall geschuldet. Die cron-expression Klasse kann ich ohne Bedenken weiterempfehlen.

        Meine DateTime-Erweiterung habe ich einfach um eine weitere Methode nextCron() ergäntzt. Nutzung z.B. so:
        PHP-Code:
        $nextRun dt::create("22.7.2017 14:00")->nextCron("20,30 1 * * 1-5");
        //2017-07-24 01:20:00 
        Dies hat speziell für mich einige Vorteile:
        • die dt Klasse ist mit hoher Wahrscheinlichkeit schon geladen. Wenn nicht, geht das schnell (nur 1 Datei). cron-expression besteht aus 10 Dateien.
        • method-chaining nutzbar
        • durch die Verfügbarkeit erweiterter Methoden für DateTime gestaltet sich die Methode sehr einfach
        Ich zeige einfach mal die Erstversion der Methode, da ich selbst überrascht war das nicht mehr notwendig war (matchCronEntry() war schon da).
        PHP-Code:
          public function nextCron($cronStr){
            
        $this->setSecond(0)->modify("+ 1 Minute");
            
        $cronArr preg_split('/\s+/',$cronStr); 
            
        //Array(Second, Minute,Hour, Day, Month, Weekday)
            
        $maxZyk 0;  //use as errorflag
            
        if(count($cronArr) == 5) {
              
        $maxZyk 200;
              
        $sequence = array(3,2,4,1,0);  //month, day, week, hour, minute
              
        while($maxZyk--){
                
        $currArr explode(' ',$this->format('i H d m w'));
                foreach(
        $sequence as $i){
                  if(!
        $this->matchCronEntry($currArr[$i], $cronArr[$i])){
                    if(
        $i==3$this->modify('first Day of next Month  00:00'); //month
                    
        elseif($i == OR $i == 4$this->modify('next Day 00:00'); //day
                    
        elseif($i == 1$this->modify('+1 hour')->setTime(null,0,0); //hour
                    
        else $this->modify('+1 minute');  //minute
                    
        continue 2;
                  }
                }
                break;
              }
            }
            if(
        $maxZyk) return $this;
            
        trigger_error('invalid Parameter $cronStr "'.$cronStr.'" for '.__METHOD__E_USER_WARNING);
            return 
        false;
          } 
        Erste Beispiele funktionieren, erweiterte Test stehen noch aus.

        Kommentar


        • #5
          Kurz am Rande:

          da … für die cron-expression Klasse PHP 7.0+ gefordert wird
          Bis Version 1.2 (die aktuelle Release-Version, Stand jetzt) wird PHP ab 5.3 aufwärts unterstützt.

          Siehe Changelog des master-Branches: https://github.com/mtdowling/cron-ex...r/CHANGELOG.md
          Und .travis.yml-File oder README des v1.2.0-Tags: https://github.com/mtdowling/cron-ex....0/.travis.yml

          Kommentar


          • #6
            Umgesetzt in der Klasse dt (class.dt.php (beta) ) wurde die klassische Cron-Syntax mit einigen kleinen Einschränkungern.

            Code:
            *          immer
            Ziffern    Wenn übereinstimmung
            Liste      wenn eine der Ziffern übereinstimmt
                       Listenvarianten: 1-5 oder 1,2,3,4,5
            */i        Alle i (Wenn akt Ziffer%i == 0 ist), z.B. */10 ist wie 0,10,20,..
            n-m/i      Im Bereich n-m alle i, z.B. 12-59/10 ist wie 12,22,32,42,52
            Beispiele
            Code:
            Minute Stunde   Tag  Monat  Wochentag  Bedeutung
            ---------------------------------------------------------
            *       *       *    *      *          jede Minute
            0       0       *    *      *          täglich 0 Uhr
            5       *       *    *      *          Fünf Minuten nach jeder vollen Stunde
            0,30    *       *    *      1-5        Mo-Fr, jede Stunde x:00 und x:30
            */15    *       *    *      *          Alle 15 Minuten, x:00, x:15, ..
            Im Cronstring sind nur Ziffern zugelassen, also keine Monatsangaben wie DEZ. Für die Wochentage sind die Ziffern 0..6 vorgesehen, 1 für Montag, 0 für Sonntag.
            Mit diesen Einschränkungen kann ich leben. Ist die Frage, ob das allgemein auch so gesehen wird..
            Es stehen nur 2 Methoden zur Verfügung
            1. isCron($cronStr) prüft, ob die aktuelle Zeit die mit dem Cronstring gegebene Bedingung erfüllt
            2. nextCron($cronStr) liefert immer den nächsten Zeitpunkt für welchen die Bedingung erfüllt wird
            Hintergrund ist eine kurze Bedingung für zukünftige Zeiten oder Intervalle zu haben, die mit der Klasse bequem abgefragt werden kann, z.B. für einen zyklischen Versand von Mails oder anderer Nachrichten.

            LG jspit

            Kommentar

            Lädt...
            X