CronTool
Cron expression editor & debugger

dragonmantank/cron-expression — PHP cron parser guide

dragonmantank/cron-expression is the de-facto cron parser for PHP — used by Laravel scheduling, Symfony Scheduler, and most modern PHP scheduling libraries. It supports the standard 5-field syntax plus the L, W, ? and # modifiers used by Quartz / AWS EventBridge dialects.
For last-day-of-month with this library see the dedicated guide.

Examples

  • 018***
    Every day at 18:00
  • 0*/5***
    Every 5 hours
  • 018**1-5
    Weekdays at 18:00
  • 001**
    Once a month

Cheatsheet

FieldRequiredValues RangeWildcardsminuteYes0-59, - * / hourYes0-59, - * / day of monthYes1-31, - * / L W monthYes1-12, - * /day of weekYes0-7, - * / L

Calendar

View future cron matches in a calendar

April 2026

Showing next 1000 cron schedules

Loading...

Using cron-expression directly

<?php
require 'vendor/autoload.php';
use Cron\CronExpression;

$cron = new CronExpression('0 9 * * 1-5');

// Is the cron due right now?
if ($cron->isDue()) {
    runJob();
}

// When does it fire next?
$next = $cron->getNextRunDate();
echo $next->format('Y-m-d H:i'); // e.g. "2026-04-27 09:00"

// Multi-step preview
foreach ($cron->getMultipleRunDates(5) as $date) {
    echo $date->format('Y-m-d H:i') . "\n";
}

Laravel scheduling on top of cron-expression

<?php
// app/Console/Kernel.php

protected function schedule(Schedule $schedule)
{
    $schedule->command('reports:daily')
             ->dailyAt('09:00')
             ->timezone('America/New_York');

    $schedule->command('billing:close-month')
             ->lastDayOfMonth();   // → '0 0 L * *'

    $schedule->command('cleanup:hourly')
             ->cron('15 * * * *'); // raw cron expression
}

Laravel's named helpers compile to cron expressions under the hood. lastDayOfMonth() uses L, which the underlying parser supports.

Symfony Scheduler on top of cron-expression

<?php

use Symfony\Component\Scheduler\Attribute\AsSchedule;
use Symfony\Component\Scheduler\Schedule;
use Symfony\Component\Scheduler\ScheduleProviderInterface;
use Symfony\Component\Scheduler\Trigger\CronExpressionTrigger;

#[AsSchedule('default')]
final class DefaultSchedule implements ScheduleProviderInterface
{
    public function getSchedule(): Schedule
    {
        return (new Schedule())
            ->add(
                CronExpressionTrigger::fromSpec('0 9 * * 1-5')
                    ->message(new MorningDigestMessage()),
                CronExpressionTrigger::fromSpec('0 0 L * *')
                    ->message(new MonthEndMessage()),
            );
    }
}

Modifier support

  • L — last day of month or last weekday-of-month.
  • LW — last weekday of the month.
  • W — nearest weekday to the given day-of-month.
  • ? — no specific value (compatibility token).
  • # — Nth weekday of month, e.g. 2#1 = first Monday.

Pitfalls

  • Default timezone — `getNextRunDate()` uses the PHP default timezone. Set it via date_default_timezone_set or pass an explicit DateTimeZone.
  • Laravel scheduler precision — runs every minute via a single OS cron, so jobs fire somewhere in their target minute (not at the exact second).
  • Backward-compat with v1 — older versions used CronExpression::factory(). New code uses new CronExpression(...).

Frequently asked questions

What PHP versions does dragonmantank/cron-expression support?

Version 3.x requires PHP 8.0+. Version 2.x supports PHP 7.2+. Both versions support `L`, `W`, `?`, `#` modifiers and standard cron syntax. Use the latest 3.x branch for new projects.

Is this what Laravel uses for its scheduler?

Yes. Laravel's task scheduler is built on top of dragonmantank/cron-expression. The named helpers (`->daily()`, `->weekdays()`, `->lastDayOfMonth()`) compile down to cron strings the parser handles.

Does Symfony Scheduler also use this?

Symfony Scheduler 6.3+ uses cron-expression internally. The `CronExpressionTrigger` class wraps a cron string and resolves the next run time using dragonmantank's parser.

What's the difference between `isDue()` and `getNextRunDate()`?

`isDue()` checks whether the cron should fire right now (matches the current minute). `getNextRunDate()` returns the next time the cron will fire. Use `isDue()` inside a per-minute scheduler loop; use `getNextRunDate()` when computing future schedules.

Ready to schedule it?

Point Crontap at any URL. Pick any cron. Done.

WordPress, Shopify, Railway, Cloud Run, Vercel, HubSpot, Ghost, your own box. If it answers HTTP, Crontap can drive it on a clock you can read, in the timezone that actually matters, and page you when something breaks.

Free forever tier ・ No credit card required

Your next schedule
GET/wp-cron.php?doing_wp_cron=1

Schedule

every 5 minutes

Next run

in 23s

Apihustle Logo

This tool is part of the Apihustle suite - a collection of tools to test, improve and get to know your API inside and out.

  • Clobbr logo

    Clobbr

    The app & CLI tool to test API endpoint speed.

    Visit
  • Crontap logo

    Crontap

    Schedule recurring API calls using cron syntax.

    Visit
  • CronTool logo

    CronTool

    Debug multiple cron expressions on a calendar.

    Visit

  • Page AI

    AI Website Generator that designs and writes clean code.

    Visit
  • Shipixen

    Generate customized boilerplates in minutes.

    Visit
  • Page UI

    Landing page UI components for React & Next.js

    Visit