CRON for PHP: Calculate the next or previous run date and determine if a CRON expression is due

Overview

PHP Cron Expression Parser

Latest Stable Version Total Downloads Build Status

NOTE This fork has been deprecated and development moved to https://github.com/dragonmantank/cron-expression. More information can be found in the blog post here. tl;dr - v2.0.0 is a major breaking change, and @dragonmantank can better take care of the project in a separate fork.

The PHP cron expression parser can parse a CRON expression, determine if it is due to run, calculate the next run date of the expression, and calculate the previous run date of the expression. You can calculate dates far into the future or past by skipping n number of matching dates.

The parser can handle increments of ranges (e.g. */12, 2-59/3), intervals (e.g. 0-9), lists (e.g. 1,2,3), W to find the nearest weekday for a given day of the month, L to find the last day of the month, L to find the last given weekday of a month, and hash (#) to find the nth weekday of a given month.

Installing

Add the dependency to your project:

composer require mtdowling/cron-expression

Usage

<?php

require_once '/vendor/autoload.php';

// Works with predefined scheduling definitions
$cron = Cron\CronExpression::factory('@daily');
$cron->isDue();
echo $cron->getNextRunDate()->format('Y-m-d H:i:s');
echo $cron->getPreviousRunDate()->format('Y-m-d H:i:s');

// Works with complex expressions
$cron = Cron\CronExpression::factory('3-59/15 2,6-12 */15 1 2-5');
echo $cron->getNextRunDate()->format('Y-m-d H:i:s');

// Calculate a run date two iterations into the future
$cron = Cron\CronExpression::factory('@daily');
echo $cron->getNextRunDate(null, 2)->format('Y-m-d H:i:s');

// Calculate a run date relative to a specific time
$cron = Cron\CronExpression::factory('@monthly');
echo $cron->getNextRunDate('2010-01-12 00:00:00')->format('Y-m-d H:i:s');

CRON Expressions

A CRON expression is a string representing the schedule for a particular command to execute. The parts of a CRON schedule are as follows:

*    *    *    *    *
-    -    -    -    -
|    |    |    |    |
|    |    |    |    |
|    |    |    |    +----- day of week (0 - 7) (Sunday=0 or 7)
|    |    |    +---------- month (1 - 12)
|    |    +--------------- day of month (1 - 31)
|    +-------------------- hour (0 - 23)
+------------------------- min (0 - 59)

Requirements

  • PHP 7.0+
  • PHPUnit is required to run the unit tests
  • Composer is required to run the unit tests
Comments
  • Wrong nextRunDate for * rules

    Wrong nextRunDate for * rules

    Thanks for library. But it gives wrong result for * rules (0 0 1 */3 * should run 1,4,7,10 month, in fact it runs on 3,6,9,12).

    Please see this discussion for more info.

    opened by decadence 15
  • Memory leaks with Opcache

    Memory leaks with Opcache

    In PHP 5.5 with the builtin Opcache enabled for the CLI using the CronExpression causes memory leaks.

    opcache.enable_cli = 1

    Execute the following script on the command line:

    use Cron\CronExpression;
    
    $expression = CronExpression::factory('25 0 1 * *');
    
    while (true) {
        $expression->isDue();
    
        usleep(100000);
    }
    

    The used memory (RSS) will increase rapidly and PHP will eventually throw a fatal error.

    Please note that when changing the expression to * * * * * this issue does not occur.

    It may very well be an issue with the Opcache, however I haven't been able to pinpoint exactly what is happening here.

    Tested on CentOS 6.4 and Mac OS X 10.9.2 with PHP 5.5.10 and PHP 5.5.11

    opened by ghost 11
  • No way to pass DateTime with custom TimeZone to isDue

    No way to pass DateTime with custom TimeZone to isDue

    In Laravel's scheduler component, we allow the user to specify a Timezone to evaluate the Cron against. However, cron-expression appears to always overwrite the timezone to the current application timezone, allowing no custom timezone to be set.

    Is there any way this can be resolved?

    opened by taylorotwell 10
  • Mark this as abandoned on packagist

    Mark this as abandoned on packagist

    Since this repo no longer sees any development (since it has continued in a different repo), it makes sense to mark the accompanying package as abandoned on packagist.

    opened by SamMousa 9
  • getPreviousRunDate fails on @weekly with the date being March 17, 2013

    getPreviousRunDate fails on @weekly with the date being March 17, 2013

    Hello.

    Just had a cron run this weekend and my script failed. Looks like it's having trouble finding the previous run date on the day of March 17, 2013. The cron expression being used is weekly.

    Thanks, Kyle

    opened by kkirby 9
  • impossible cron issue

    impossible cron issue

    this cron 13 14 3 2 3 throws the impossible cron exception

    if i test it ( http://cron.schlitt.info/index.php?cron=13+14+3+2+3&iterations=10&test=Test ), i should get:

    2016-02-03 14:13:00
    2016-02-10 14:13:00
    2016-02-17 14:13:00
    2016-02-24 14:13:00
    2017-02-01 14:13:00
    2017-02-03 14:13:00
    2017-02-08 14:13:00
    2017-02-15 14:13:00
    2017-02-22 14:13:00
    2018-02-03 14:13:00
    ...
    
    opened by patrioticcow 8
  • cron-expression throws an error when checking an expired cron expression

    cron-expression throws an error when checking an expired cron expression

    I have noticed that I get a "Impossible CronExpression" error any time I have a cron expression that has expired or is in the past.

    A little background on how we are using cron-expression. We have maintenance schedules which are scheduled via cron expressions, which makes perfect sense as many are recurring on a set schedule. However, there are times when the maintenance schedule is just for a couple of hours early in the morning and it is a one time thing. That is when we start running into issues.

    Example: If today's date/time is 1/29/2015 12:00 and we have a cron expression for a maintenance schedule of "* 1-4 29 1 * 2015" we will get a "Impossible CronExpression" error thrown when checking it through the IsDue() method. Which I assume is because that expression represents a time in the past.

    For entering a new cronExpression for a time in the past, an error or warning like this makes sense, but not for a cronExpression that, when entered, was/is valid and as time goes it becomes a time in the past. That should not error out I would think. Any ideas as to why this is happening? And how one would go about fixing it?

    Any help on this issue would be most appreciated.

    Thanks,

    • Barrett-
    opened by ghoastfalcon 8
  • added minute interval allowance

    added minute interval allowance

    Love this code...thank you...it has solved and consolidated many things for me. The one "problem" I had was that running my "cron" every minute was going to be too much. So, I looked into running it every 10 minutes and having the code detect what should have run within those 10 minutes.

    I updated the isDue function to allow an interval of minutes to be checked so that you would not need to run this function "once per minute" and could pick up events within the designated interval. also added tests to demonstrate usage and check the boundaries.

    opened by dscone 8
  • Improvement: accept DateTimeImmutable where appropriate on public-facing APIs

    Improvement: accept DateTimeImmutable where appropriate on public-facing APIs

    A couple of public-facing APIs are prepared to accept DateTime instances, but not DateTimeImmutable. This PR updates the code so that it also accepts DateTimeImmutable.

    I tried to make the minimum possible volume of modifications, which means that the result doesn't read as nicely as fresh code written with PHP 5.5 in mind. I'm willing to rewrite more if that is required.

    opened by TheDistantSea 7
  • Issue with cron

    Issue with cron

    Hi , I am from India and my Timezone is UTC +5:30

    now the problem that arises to me is that assume the cron entry is "25 0 * * *"

    the time now say is 2014-05-13 17:19:00 so the next run time is 2014-05-14 00:25:00

    in first loop obviously 0 doesn't match with 17 so the 17 is incremented .. but here is the issue .. as we are converting to UTC and back .. after increment the time changes to .2014-05-13 17:30:00 notice that the minute is now 30 which is greater than 25.

    after the increments are as follows 2014-05-13 17:30:00 2014-05-13 18:30:00 2014-05-13 19:30:00 2014-05-13 20:30:00 2014-05-13 21:30:00 2014-05-13 22:30:00 2014-05-13 23:30:00 2014-05-14 00:30:00

    And here the cron expression has been completely missed out and the system gets into an infinite loop

    for the time being I have removed the covert to UTC and back feature as we don't need to deal with DST

    opened by ap-aravind 7
  • New release?

    New release?

    Hi there, this looks awesome and I'm considering using it for piwik but it looks like the last release is a year old (51 commits behind master).

    Is that possible to tag a new release?

    If it helps getting there faster, here is the changelog:

    • Avoid infinity loop & division by zero #67
    • Fix getRunDate() shouldn't modify currentTime parameter #57
    • Missing anchors in regexp #63
    • Avoid annotation parsing by Doctrine #62
    • Optimization #52
    • Fixed #20 Weekday-Hash for Saturday and Sunday doesn't seem to work #53
    • Different timezone support #48
    • Fixed regexp for day of week #49
    • Set $currentTime as 'now' #36

    I kept only the changes meaningful for end-users (e.g. not changes about tests or docs).

    opened by mnapoli 6
  • Invalid CRON field value 1/2 at position 2

    Invalid CRON field value 1/2 at position 2

    dragonmantank\cron-expression (v3.1.0)

    $expr = '0 0 1/2 * *'; $cron = \Cron\CronExpression::factory($expr); echo $cron->getNextRunDate()->format('Y-m-d H:i:s');

    InvalidArgumentException in C:\vendor\dragonmantank\cron-expression\src\Cron\CronExpression.phpat line 158 Invalid CRON field value 1/2 at position 2

    mtdowling/cron-expression (v. 1.2.3) execute this code correct (w/o Exception)

    opened by 4meck 1
  • If result of getNextRunDate / getPreviousRunDate happens to be during DST change window, exception is thrown

    If result of getNextRunDate / getPreviousRunDate happens to be during DST change window, exception is thrown

    If the result of getPreviousRunDate happens to be within the "missing" hour during DST change, an "Impossible CRON expression" error is thrown.

    opened by eirikmik 3
  • Impossible CRON Expression

    Impossible CRON Expression

    I'm getting an 'impossible cron expression' error which seems to be a combination of day of the week, the Sydney timezone, and the particular 'current date' of 3/27.

    $dateTime = Cron\CronExpression::factory('0 0 * * 1')->getNextRunDate(Carbon\Carbon::create(2017, 3, 27, 0, 0, 0, 'UTC')->timezone('Australia/Sydney'));
    
    opened by brianwebb01 1
  • Settings the day of week and day of month.

    Settings the day of week and day of month.

    If both fields are restricted (for day of month and day of week) a cron should match for either case, as per the cron man:

     Note: The day of a command's execution can be specified by two fields --
     day of month, and day of week.  If both fields are restricted (ie, are
     not *), the command will be run when either field matches the current
     time.  For example, ``30 4 1,15 * 5'' would cause a command to be run at
     4:30 am on the 1st and 15th of each month, plus every Friday.
    

    However, in a test with the following expression:

    0 16 4 * fri *

    The expected behavior is every Friday OR every month on the 4th.

    However, when running this, it matches if it is a Friday AND it is the forth: here is sample output:

    Next: Fri, 04 Nov 2016 16:00:00 +0000 Last: Fri, 04 Mar 2016 16:00:00 +0000

    Great library otherwise.

    opened by treadon 2
  • Daylight savings time considerations

    Daylight savings time considerations

    I didn't notice anything in the source handling daylight savings time. Cron's consideration for this is that any time changes less than 3 hours should be considered daylight savings time.

    Not handling this would mean that hour-based runs could run more than they are suppose to. For example if something were scheduled for 2AM it would run twice when rolling back.

    See: https://www.pantz.org/software/cron/croninfo.html

    opened by mc0 4
Releases(v1.2.0)
  • v1.2.0(Jan 23, 2017)

    Added

    • Added IDE, CodeSniffer, and StyleCI.IO support

    Changed

    • Switched to PSR-4 Autoloading

    Fixed

    • 0 step expressions are handled better
    • Fixed DayOfMonth validation to be more strict
    • Typos
    Source code(tar.gz)
    Source code(zip)
  • v1.1.0(Jan 23, 2017)

    Added

    • Support for non-hourly offset timezones
    • Checks for valid expressions

    Changed

    • Max Iterations no longer hardcoded for getRunDate()
    • Supports DateTimeImmutable for newer PHP verions

    Fixed

    • Fixed looping bug for PHP 7 when determining the last specified weekday of a month
    Source code(tar.gz)
    Source code(zip)
  • v1.0.4(Jan 11, 2015)

    • Avoid infinity loop & division by zero #67
    • Fix getRunDate() shouldn't modify currentTime parameter #57
    • Missing anchors in regexp #63
    • Avoid annotation parsing by Doctrine #62
    • Optimization #52
    • Fixed #20 Weekday-Hash for Saturday and Sunday doesn't seem to work #53
    • Different timezone support #48
    • Fixed regexp for day of week #49
    • Set $currentTime as 'now' #36
    • Allowing multiple values for day of week field.
    Source code(tar.gz)
    Source code(zip)
  • v1.0.3(Nov 23, 2013)

    • Only set default timezone if the given $currentTime is not a DateTime instance (#34)
    • Fixes issue #28 where PHP increments of ranges were failing due to PHP casting hyphens to 0
    • Now supports expressions with any number of extra spaces, tabs, or newlines
    • Using static instead of self in CronExpression::factory
    Source code(tar.gz)
    Source code(zip)
🤖 GitHub Action to run symfony console commands.

Symfony Console GitHub Action Usage You can use it as a Github Action like this: # .github/workflows/lint.yml name: "Lint" on: pull_request: push

Nucleos 3 Oct 20, 2022
A PHP Command Line tool that makes it easy to compile, concat, and minify front-end Javascript and CSS/SCSS dependencies.

Front End Compiler A PHP Command Line tool that makes it easy to compile, concat, and minify front-end Javascript and CSS/SCSS dependencies. The minif

Happy Medium 2 Nov 12, 2021
Web Shell Detector – is a php script that helps you find and identify php/cgi(perl)/asp/aspx shells.

Web Shell Detector – is a php script that helps you find and identify php/cgi(perl)/asp/aspx shells. Web Shell Detector has a “web shells” signature database that helps to identify “web shell” up to 99%. By using the latest javascript and css technologies, web shell detector has a light weight and friendly interface.

Maxim 763 Dec 27, 2022
Termage provides a fluent and incredibly powerful object-oriented interface for customizing CLI output text color, background, formatting, theming and more.

Termage provides a fluent and incredibly powerful object-oriented interface for customizing CLI output text color, background, formatting, theming and

TERMAGE 75 Dec 20, 2022
Twitter raffles in the command line, with PHP and minicli

Rafflebird Rafflebird is a highly experimental CLI application for giveaways / raffles on Twitter, built in PHP with Minicli. Disclaimer: The recent s

Erika Heidi 33 Nov 16, 2022
Command-line control panel for Nginx Server to manage WordPress sites running on Nginx, PHP, MySQL, and Let's Encrypt

EasyEngine v4 EasyEngine makes it greatly easy to manage nginx, a fast web-server software that consumes little memory when handling increasing volume

EasyEngine 2k Jan 4, 2023
unofficial cli built using php which can be used to upload and download files from anonfiles.com

Anonfiles CLI Table of Contents Introduction Features Screenshots Installation Contributing License Introduction Anon Files CLI can upload and downloa

Albin Varghese 8 Nov 21, 2022
PHP Interminal is a command-line tool that gives you access to PHP Internals discussions in your terminal.

PHP Interminal is a command-line tool that gives you access to PHP Internals discussions in your terminal. ??

Nuno Maduro 32 Dec 26, 2022
PHP Reverse Shell > reverse-shell.php

PHP Reverse Shell > reverse-shell.php PHP Cmd Shell > cmd.php JPG cmd Shell > cmd.jpg /etc/passwd Pulling Shell > etc-passwd.php Configuration Pulling

Dark-Network 5 Feb 24, 2022
A CLI program that helps you check your endpoints by requesting the given servers and send a report message in any supported channel like Telegram

API Monitor A CLI program that help you check your endpoints by requesting the given servers and send a report message in any supported channel ( Tele

Hussein Feras 51 Aug 21, 2022
A Magento 2 module that adds a CLI bin/magento cms:dump to dump all CMS pages and CMS blocks to a folder var/cms-output.

A Magento 2 module that adds a CLI bin/magento cms:dump to dump all CMS pages and CMS blocks to a folder var/cms-output.

Yireo 16 Dec 16, 2022
Console - The Console component eases the creation of beautiful and testable command line interfaces.

Console Component The Console component eases the creation of beautiful and testable command line interfaces. Sponsor The Console component for Symfon

Symfony 9.4k Jan 7, 2023
Deactivate and activate a plugin with just one in-game command

DEPlugins | v1.0.0 ✔️ Deactivate and activate a plugin with just one in-game command ✔️ Features Deactivate and activate a plugin with just one in-gam

Noob MCBG 0 Apr 17, 2022
A tool to generate boilerplate code, interact with and debug Drupal.

Table of Contents generated with DocToc Drupal Console Required PHP version Drupal Console documentation Download Drupal Console Run Drupal Console Co

Hecho en Drupal 929 Jan 5, 2023
Provides the equivalent of request ( Context ) and response ( Stdio ) objects for the command line interface

Provides the equivalent of request ( Context ) and response ( Stdio ) objects for the command line interface, including Getopt support, and an independent Help object for describing commands.

Aura for PHP 103 Sep 28, 2022
A Cli tool to save you time, and gives you the power to scaffold all of your models,controllers,commands

A Cli tool to save you time, and gives you the power to scaffold all of your models,controllers,commands... at once Installation You can install the p

Coderflex 16 Nov 11, 2022
Hentai Bash - This is the core of Hentai Terminal, responsible for the basic functions and commands

Hentai Bash - This is the core of Hentai Terminal, responsible for the basic functions and commands. It is mainly used for writing and executing commands.

Hentai Group 1 Jan 26, 2022
Cecil is a CLI application that merges plain text files (written in Markdown), images and Twig templates to generate a static website.

Cecil is a CLI application that merges plain text files (written in Markdown), images and Twig templates to generate a static website.

Cecil 209 Jan 2, 2023