Home › Cron Syntax

Cron Syntax Reference Guide

A complete reference for cron expression syntax. Covers Linux crontab, Quartz Scheduler, AWS EventBridge, Kubernetes and Spring Boot, including all special characters, operators and macros.

Cron Expression Field Structure

A Linux cron expression consists of five fields separated by spaces, followed by the command to execute. Each field defines a time unit, and together they specify exactly when the job should run.

*   *   *   *   *
|   |   |   |   |
|   |   |   |   +-- Day of week  (0-6, Sun=0)
|   |   |   +------ Month       (1-12)
|   |   +------------ Day of month  (1-31)
|   +------------------ Hour        (0-23)
+---------------------- Minute      (0-59)

Example: 0 9 * * 1-5 runs every weekday at 9:00 AM.

Field Required Values Special characters allowed
Minute Yes 0-59 * , - /
Hour Yes 0-23 * , - /
Day of month Yes 1-31 * , - / ? L W
Month Yes 1-12 or JAN-DEC * , - /
Day of week Yes 0-6 (Sun=0) or SUN-SAT * , - / ? L #

Special Characters

Char Name Meaning Example Result
* Asterisk Any value - matches every possible value for that field * * * * * Every minute
, Comma Value list - matches any of the listed values 0 6,18 * * * At 6:00 AM and 6:00 PM daily
- Hyphen Range - matches any value between start and end (inclusive) 0 9-17 * * * Every hour from 9 AM to 5 PM
/ Slash Step - defines intervals. */n means every n units */15 * * * * Every 15 minutes
? Question mark No specific value. Used in day-of-month or day-of-week when the other is set. Quartz and AWS only. 0 0 1 * ? First of month, any weekday
L Last Last day of month or last weekday of month. Quartz only. 0 0 L * ? Last day of every month
W Weekday Nearest weekday (Mon-Fri) to a given day. Quartz only. 0 0 15W * ? Nearest weekday to the 15th
# Hash Nth weekday of month. 2#1 = first Monday. Quartz only. 0 0 ? * 2#1 First Monday of every month

Month Names

NumberNameAbbreviation
1JanuaryJAN
2FebruaryFEB
3MarchMAR
4AprilAPR
5MayMAY
6JuneJUN
7JulyJUL
8AugustAUG
9SeptemberSEP
10OctoberOCT
11NovemberNOV
12DecemberDEC

Day of Week Names

NumberDayAbbreviation
0 or 7SundaySUN
1MondayMON
2TuesdayTUE
3WednesdayWED
4ThursdayTHU
5FridayFRI
6SaturdaySAT

Predefined Macros

Linux crontab supports shorthand strings that replace the five-field expression.

MacroEquivalentDescription
@yearly / @annually0 0 1 1 *Once a year at midnight on January 1st
@monthly0 0 1 * *Once a month at midnight on the 1st
@weekly0 0 * * 0Once a week at midnight on Sunday
@daily / @midnight0 0 * * *Once a day at midnight
@hourly0 * * * *Once an hour at the beginning of the hour
@rebootn/aOnce at system startup

Cron Syntax by Platform

Different platforms use slightly different cron formats. Here is a full comparison.

Feature Linux / Unix Quartz (Java) AWS EventBridge Kubernetes Spring Boot
Number of fields 5 6-7 6 5 6
Seconds field No Yes (1st field) No No Yes (1st field)
Year field No Optional (7th) Required (6th) No No
? operator No Yes Yes No Yes
L operator No Yes No No Yes
W operator No Yes No No Yes
# operator No Yes No No Yes
Timezone Server TZ App TZ UTC only Server TZ App TZ
Day/weekday conflict OR logic Use ? Use ? OR logic Use ?

Things That Will Actually Bite You

These are not edge cases. Every developer hits at least two of these on their first cron job in production.

Cron's PATH is not your PATH

Cron runs with a stripped-down environment. php, node, python - none of them are on cron's PATH by default. Your script works fine when you run it manually and fails silently every night. Use full paths:

0 2 * * * /usr/bin/php /var/www/html/script.php

Run which php to find the full path on your server.

Silent failures are the default

By default, cron discards all output. If your script crashes, you will never know. Always redirect both stdout and stderr to a log file:

0 2 * * * /path/script.sh >> /var/log/myjob.log 2>&1

The 2>&1 part redirects errors too. Without it you only see half the picture.

Timezone mismatch

Cron uses the server's system timezone - not UTC, not your local time, not the app's timezone. Your backup runs at "2 AM" but which 2 AM depends entirely on what timedatectl says. AWS EventBridge is the only platform that always uses UTC, which is actually a feature. Check your timezone before assuming anything: cat /etc/timezone

Day-of-month AND day-of-week is OR, not AND

In Linux cron, 0 9 1 * 1 does not mean "the 1st of the month if it falls on Monday". It means "the 1st of the month, OR any Monday". Most people expect AND logic here and get surprised. If you need AND logic (run only when both conditions are true), you need to add a date check inside the script itself.

Cron Syntax in CI/CD Platforms

Most CI/CD platforms use standard 5-field Unix cron syntax in UTC. The main difference is where you write it - a YAML file instead of a crontab.

GitHub Actions

Standard 5-field cron in UTC. Minimum interval is every 5 minutes.

on:
  schedule:
    - cron: '0 2 * * *'

GitHub may delay scheduled runs during peak load.

GitLab CI

Configured in the GitLab UI under CI/CD › Schedules, not in the YAML. Uses standard 5-field syntax.

0 4 * * 1-5

Timezone is configurable per schedule in GitLab.

Jenkins

Jenkins uses standard cron syntax in the triggers block. Also supports H (hash) to spread load across jobs.

triggers {
  cron('0 2 * * *')
}

H * * * * means "once per hour at an arbitrary minute" - useful to avoid all jobs firing at :00.

CircleCI

Defined in .circleci/config.yml under triggers. Standard 5-field syntax in UTC.

triggers:
  - schedule:
      cron: "0 0 * * *"
      filters:
        branches:
          only: main

CircleCI requires a filters.branches block - easy to forget.

Build and validate your cron expression

Paste it in the checker if you are not sure. It takes two seconds and saves you a midnight debugging session.