Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Calculate all run dates between two dates #1

Open
geryguilbon opened this issue Nov 4, 2017 · 3 comments
Open

Calculate all run dates between two dates #1

geryguilbon opened this issue Nov 4, 2017 · 3 comments
Labels
looking for votes Features requests I'm leaving open to gauge interest

Comments

@geryguilbon
Copy link

I think this could be great to have this feature implemented =)

@ComlOnline
Copy link

ComlOnline commented Nov 17, 2017

Not pretty or very good but this works:

<?php
$start = "2010-01-12 00:00:00";
$end = "2011-01-13 00:00:00";
$ahead = 0;
$cron = Cron\CronExpression::factory('@monthly');
$init = $cron->getNextRunDate($start, $ahead)->format('Y-m-d H:i:s');
while (strtotime($init) <= strtotime($end)) {
                echo "<pre>$init\n<pre>";
                $ahead++;
                $init =  $cron->getNextRunDate($start, $ahead)->format('Y-m-d H:i:s');
}
?>

@dragonmantank dragonmantank added the looking for votes Features requests I'm leaving open to gauge interest label Jan 5, 2022
@va5ja
Copy link

va5ja commented Nov 22, 2022

Same for "get next X runs" or is that possible already?

@cottton
Copy link

cottton commented Jul 29, 2023

Needed a from-to last days ...
here is a concept i would suggest:

EDIT: i just realizeed that the param $invert makes no sense in this method. So ignore it - should be provided as false always at getMultipleRunDates =)

function getMultipleRunDatesByTimeframe(
    $cronExpression,
    $from = 'now',
    $to = 'now + 1 hour',
    // bool $invert = false,
    bool $allowCurrentDate = false,
    $timeZone = null
) {
    $model = new CronExpression($cronExpression);
    $from = new DateTime($from);
    $to = new DateTime($to);

    $matches = [];
    while ($from <= $to) {
        $match = $model->getMultipleRunDates(
            1, // $total,
            $from, // $currentTime,
            false, // $invert,
            $allowCurrentDate,
            $timeZone
        )[0];
        $matches[] = $match;
        // After every run re-set the $from var to not run into "Impossible CRON expression".
        // Example:
        // $cronExpression  : "*/15 * * * *"
        // $from            : "2023-07-29 16:12:49"
        // $match           : "2023-07-29 16:15:00"
        // $from re-set     : "2023-07-29 16:15:00"
        $from = clone $match;
        // After the first run we need to set the var $allowCurrentDate to value false
        // to not keep looping on the same datetime.
        // Example:
        // we just got "2023-07-29 19:15:00"
        // and would get "2023-07-29 19:15:00" again, and again, ... .
        $allowCurrentDate = false;
    }
    return $matches;
}

$cronExpression = '*/15 * * * *';
$from = 'now';
$to = 'now + 1 hour';
// $invert = false;
$allowCurrentDate = true;
$timeZone = null;
$matches = getMultipleRunDatesByTimeframe(
    $cronExpression,
    $from,
    $to,
    // $invert,
    $allowCurrentDate,
    $timeZone
);

I used getMultipleRunDates because its public unlike getRunDate.
I choose to get always 1 single run date to not run into $maxIterationCount error.
And this makes it actually pretty fast. Expression */15 * * * * from 2023-01-01 to 2023-12-31 took 0.354930 sec.


Suggestions:

One single method to get datetime input to datetime object

There are atm 3 places of $currentTime checks at
https://github.com/dragonmantank/cron-expression/blob/master/src/Cron/CronExpression.php#L317
https://github.com/dragonmantank/cron-expression/blob/master/src/Cron/CronExpression.php#L403
https://github.com/dragonmantank/cron-expression/blob/master/src/Cron/CronExpression.php#L445
I would suggest to add a new method getDatetimeObject($datetime) to be able to

  • reuse code
  • and be able to use it for other datetime parameters.

New method to get multiple run dates by timeframe

Implement a metod getMultipleRunDatesByTimeframe(...) like

public function getMultipleRunDatesByTimeframe(
    $from = 'now',
    $to = 'now + 1 hour',
    // bool $invert = false,
    bool $allowCurrentDate = false,
    $timeZone = null
): array {}

and use the new|suggested getDatetimeObject(...) method to

  • get a datetime object by providing the $from parameter
  • get a datetime object by providing the $to parameter.

The code for this method would be ofc the one in the concept above, without the need of the cron expression model creation.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
looking for votes Features requests I'm leaving open to gauge interest
Projects
None yet
Development

No branches or pull requests

5 participants