Skip to content

How to validate a 5-field cron (without relying on your scheduler)

Basic validation for 5-field cron (min hour dom month dow) with *, */n and numbers. Useful to catch obvious mistakes before deploying.

← Developer Zone
Updated: 2026-03-22

Use this article when...

This section is built for speed: one concrete task, multiple stacks, and the minimum context needed not to copy the wrong thing.

Start from the exact task

These pages work best when the incident is already concrete and you need a fast implementation path.

Read notes before copying

The snippet is only useful if the runtime, dependency model, and assumptions match your environment.

Jump deeper when needed

If the problem expands into architecture, security, or production tradeoffs, stop treating it like a copy-paste task.

What this article gives you

A short path from incident to implementation: context, language-specific snippets, and the warning signs that usually get skipped.

Languages

13

Related tools

3

Topics

cron, devops, scheduling, validation

Cron has dialects. Before relying on your scheduler, validate the basics: 5 fields and in-range values. This avoids most silly PR mistakes.

These snippets validate a useful subset (*, */n, and numbers). For ranges/lists or “next run times”, use a cron library or the Cron Parser.

Dependency snapshot by language

Check this first to see which snippets use built-in/runtime APIs and which ones need external packages before you start copying code.

Bash
Check notes

Review the notes for setup details.

C#
Check notes

Review the notes for setup details.

Delphi
Check notes

Review the notes for setup details.

Go
Check notes

Review the notes for setup details.

Java
Check notes

Review the notes for setup details.

JavaScript
Check notes

Review the notes for setup details.

Kotlin
Check notes

Review the notes for setup details.

PHP
Check notes

Review the notes for setup details.

Python
Built-in

Built-in or runtime API

Ruby
Check notes

Review the notes for setup details.

Rust
Check notes

Review the notes for setup details.

TypeScript
Check notes

Review the notes for setup details.

VB.NET
Check notes

Review the notes for setup details.

How to use these code examples well

The snippet is only the fast path. The explanation and notes are what keep you from copying the wrong assumption into production.

1. Start with the problem

Make sure the article really matches the issue you are debugging before copying code just because the title looks close.

2. Read the notes

That is where portability limits, dependency requirements, and runtime assumptions usually appear.

3. Validate the output

If the code runs but the bug remains, jump to the related tool and inspect the real payload, token, timestamp, or config.

Code examples by language

Snippets that compile/run, plus short explanations and real-world notes.

Bash

bash
Bash
is_num() { [[ "$1" =~ ^[0-9]+$ ]]; }
check_field() {
  local f="$1" min=$2 max=$3
  if [ "$f" = "*" ]; then return 0; fi
  if [[ "$f" =~ ^\*/([0-9]+)$ ]]; then
    local step=${BASH_REMATCH[1]}
    is_num "$step" && [ "$step" -ge 1 ] && [ "$step" -le "$max" ]
    return $?
  fi
  if is_num "$f" && [ "$f" -ge "$min" ] && [ "$f" -le "$max" ]; then return 0; fi
  return 1
}

cron="*/5 * * * *"
read -r m h dom mon dow <<<"$cron"
if check_field "$m" 0 59 && check_field "$h" 0 23 && check_field "$dom" 1 31 && check_field "$mon" 1 12 && check_field "$dow" 0 7; then
  echo OK
else
  echo INVALID
fi
Explanation

Validates simple cron with no dependencies: 5 fields, with * or */n or a number within range. Useful as a guardrail.

Notes
  • No ranges (1-5) or lists (1,2).
  • DOW varies by platform; this example accepts 0–7.

C#

csharp
C#
using System;
using System.Text.RegularExpressions;

bool CheckField(string f, int min, int max) {
  if (f == "*") return true;
  var m = Regex.Match(f, @"^\*/(\d+)$");
  if (m.Success) {
    var step = int.Parse(m.Groups[1].Value);
    return step >= 1 && step <= max;
  }
  if (int.TryParse(f, out var n)) return n >= min && n <= max;
  return false;
}

var cron = "*/5 * * * *";
var p = cron.Split(" ", StringSplitOptions.RemoveEmptyEntries);
var ok = p.Length == 5
  && CheckField(p[0], 0, 59)
  && CheckField(p[1], 0, 23)
  && CheckField(p[2], 1, 31)
  && CheckField(p[3], 1, 12)
  && CheckField(p[4], 0, 7);
Console.WriteLine(ok ? "OK" : "INVALID");
Explanation

Split + ranges + */n support. Good first filter before using a full parser.

Notes
  • No ranges/lists.
  • For “next run” use NCrontab or another library.

Delphi

delphi
Delphi
program CronValidate;

{$APPTYPE CONSOLE}

uses
  System.SysUtils,
  System.RegularExpressions;

function CheckField(const F: string; MinV, MaxV: Integer): Boolean;
var
  N: Integer;
  M: TMatch;
begin
  if F = "*" then Exit(True);
  M := TRegEx.Match(F, "^\*/(\d+)$");
  if M.Success then
  begin
    N := StrToIntDef(M.Groups[1].Value, 0);
    Exit((N >= 1) and (N <= MaxV));
  end;
  N := StrToIntDef(F, -1);
  Result := (N >= MinV) and (N <= MaxV);
end;

var
  Cron: string;
  Parts: TArray<string>;
  Ok: Boolean;
begin
  Cron := "*/5 * * * *";
  Parts := Cron.Split([Char(32)], TStringSplitOptions.ExcludeEmpty);
  Ok := (Length(Parts) = 5)
    and CheckField(Parts[0], 0, 59)
    and CheckField(Parts[1], 0, 23)
    and CheckField(Parts[2], 1, 31)
    and CheckField(Parts[3], 1, 12)
    and CheckField(Parts[4], 0, 7);
  if Ok then Writeln("OK") else Writeln("INVALID");
end.
Explanation

Minimal validator: * / */n / number in range. For advanced cron, use a dedicated library.

Notes
  • No ranges/lists.

Go

go
Go
package main

import (
  "fmt"
  "regexp"
  "strconv"
  "strings"
)

var stepRe = regexp.MustCompile(`^\*/(\d+)$`)

func checkField(f string, min, max int) bool {
  if f == "*" {
    return true
  }
  if m := stepRe.FindStringSubmatch(f); m != nil {
    step, _ := strconv.Atoi(m[1])
    return step >= 1 && step <= max
  }
  n, err := strconv.Atoi(f)
  if err != nil {
    return false
  }
  return n >= min && n <= max
}

func main() {
  cron := "*/5 * * * *"
  p := strings.Fields(cron)
  ok := len(p) == 5 &&
    checkField(p[0], 0, 59) &&
    checkField(p[1], 0, 23) &&
    checkField(p[2], 1, 31) &&
    checkField(p[3], 1, 12) &&
    checkField(p[4], 0, 7)
  fmt.Println(map[bool]string{true: "OK", false: "INVALID"}[ok])
}
Explanation

Quick validation for simple cron with no dependencies.

Notes
  • No ranges/lists.
  • For “next run”, use a cron parser.

Java

java
Java
import java.util.regex.*;

public class Main {
  static boolean checkField(String f, int min, int max) {
    if (f.equals("*")) return true;
    Matcher m = Pattern.compile("^\*/(\d+)$").matcher(f);
    if (m.find()) {
      int step = Integer.parseInt(m.group(1));
      return step >= 1 && step <= max;
    }
    try {
      int n = Integer.parseInt(f);
      return n >= min && n <= max;
    } catch (NumberFormatException e) {
      return false;
    }
  }

  public static void main(String[] args) {
    String cron = "*/5 * * * *";
    String[] p = cron.trim().split("\s+");
    boolean ok = p.length == 5
      && checkField(p[0], 0, 59)
      && checkField(p[1], 0, 23)
      && checkField(p[2], 1, 31)
      && checkField(p[3], 1, 12)
      && checkField(p[4], 0, 7);
    System.out.println(ok ? "OK" : "INVALID");
  }
}
Explanation

Simple validation without cron libraries. Useful to avoid out-of-range values.

Notes
  • Limited.
  • For real cron, use cron-utils.

JavaScript

javascript
JavaScript
function checkField(f, min, max) {
  if (f === "*") return true;
  const step = f.match(/^\*\/(\d+)$/);
  if (step) return Number(step[1]) >= 1 && Number(step[1]) <= max;
  const n = Number(f);
  return Number.isInteger(n) && n >= min && n <= max;
}

const cron = "*/5 * * * *";
const p = cron.trim().split(/\s+/);
const ok = p.length === 5
  && checkField(p[0], 0, 59)
  && checkField(p[1], 0, 23)
  && checkField(p[2], 1, 31)
  && checkField(p[3], 1, 12)
  && checkField(p[4], 0, 7);
console.log(ok ? "OK" : "INVALID");
Explanation

Validates simple cron in JS. Perfect for pre-checks in tooling.

Notes
  • No ranges/lists.

Kotlin

kotlin
Kotlin
fun checkField(f: String, min: Int, max: Int): Boolean {
  if (f == "*") return true
  val step = Regex("^\*/(\d+)$").matchEntire(f)
  if (step != null) {
    val n = step.groupValues[1].toInt()
    return n in 1..max
  }
  val n = f.toIntOrNull() ?: return false
  return n in min..max
}

fun main() {
  val cron = "*/5 * * * *"
  val p = cron.trim().split(Regex("\s+"))
  val ok = p.size == 5
    && checkField(p[0], 0, 59)
    && checkField(p[1], 0, 23)
    && checkField(p[2], 1, 31)
    && checkField(p[3], 1, 12)
    && checkField(p[4], 0, 7)
  println(if (ok) "OK" else "INVALID")
}
Explanation

Validates simple cron in Kotlin with no dependencies.

Notes
  • Limited to *, */n, number.

PHP

php
PHP
<?php
function checkField(string $f, int $min, int $max): bool {
  if ($f === "*") return true;
  if (preg_match("/^\*\/(\d+)$/", $f, $m)) {
    $step = (int)$m[1];
    return $step >= 1 && $step <= $max;
  }
  if (!ctype_digit($f)) return false;
  $n = (int)$f;
  return $n >= $min && $n <= $max;
}

$cron = "*/5 * * * *";
$p = preg_split("/\s+/", trim($cron));
$ok = count($p) === 5
  && checkField($p[0], 0, 59)
  && checkField($p[1], 0, 23)
  && checkField($p[2], 1, 31)
  && checkField($p[3], 1, 12)
  && checkField($p[4], 0, 7);
echo $ok ? "OK\n" : "INVALID\n";
Explanation

Minimal validation for simple cron in PHP.

Notes
  • No ranges/lists.

Python

python
Python
import re

step_re = re.compile(r"^\*/(\d+)$")

def check_field(f: str, min_v: int, max_v: int) -> bool:
  if f == "*":
    return True
  m = step_re.match(f)
  if m:
    step = int(m.group(1))
    return 1 <= step <= max_v
  if f.isdigit():
    n = int(f)
    return min_v <= n <= max_v
  return False

cron = "*/5 * * * *"
p = cron.split()
ok = (
  len(p) == 5
  and check_field(p[0], 0, 59)
  and check_field(p[1], 0, 23)
  and check_field(p[2], 1, 31)
  and check_field(p[3], 1, 12)
  and check_field(p[4], 0, 7)
)
print("OK" if ok else "INVALID")
Explanation

Minimal validator in Python. For real cron, croniter is a common choice (dependency).

Notes
  • Std.
  • Timezone/DST matters in production.

Ruby

ruby
Ruby
def check_field(f, min, max)
  return true if f == "*"
  m = f.match(/^\*\/(\d+)$/)
  return (1..max).include?(m[1].to_i) if m
  return false unless f.match?(/^\d+$/)
  n = f.to_i
  n >= min && n <= max
end

cron = "*/5 * * * *"
p = cron.split
ok = p.length == 5 &&
  check_field(p[0], 0, 59) &&
  check_field(p[1], 0, 23) &&
  check_field(p[2], 1, 31) &&
  check_field(p[3], 1, 12) &&
  check_field(p[4], 0, 7)
puts(ok ? "OK" : "INVALID")
Explanation

Simple validation without gems. For “next run”, use a cron gem (fugit).

Notes
  • Limited.

Rust

rust
Rust
fn check_field(f: &str, min: i32, max: i32) -> bool {
  if f == "*" {
    return true;
  }
  if let Some(step) = f.strip_prefix("*/") {
    return step.parse::<i32>().map(|n| n >= 1 && n <= max).unwrap_or(false);
  }
  f.parse::<i32>().map(|n| n >= min && n <= max).unwrap_or(false)
}

fn main() {
  let cron = "*/5 * * * *";
  let p: Vec<&str> = cron.split_whitespace().collect();
  let ok = p.len() == 5
    && check_field(p[0], 0, 59)
    && check_field(p[1], 0, 23)
    && check_field(p[2], 1, 31)
    && check_field(p[3], 1, 12)
    && check_field(p[4], 0, 7);
  println!("{}", if ok { "OK" } else { "INVALID" });
}
Explanation

Validates a useful cron subset with no crates.

Notes
  • No ranges/lists.

TypeScript

ts
TypeScript
function checkField(f: string, min: number, max: number): boolean {
  if (f === "*") return true;
  const step = f.match(/^\*\/(\d+)$/);
  if (step) return Number(step[1]) >= 1 && Number(step[1]) <= max;
  const n = Number(f);
  return Number.isInteger(n) && n >= min && n <= max;
}

const cron = "*/5 * * * *";
const p = cron.trim().split(/\s+/);
const ok = p.length === 5
  && checkField(p[0], 0, 59)
  && checkField(p[1], 0, 23)
  && checkField(p[2], 1, 31)
  && checkField(p[3], 1, 12)
  && checkField(p[4], 0, 7);
console.log(ok ? "OK" : "INVALID");
Explanation

Minimal validator in TS.

Notes
  • Limited.

VB.NET

vbnet
VB.NET
Imports System
Imports System.Text.RegularExpressions

Module Program
  Private Function CheckField(f As String, min As Integer, max As Integer) As Boolean
    If f = "*" Then Return True
    Dim m = Regex.Match(f, "^\*/(\d+)$")
    If m.Success Then
      Dim stepN = Integer.Parse(m.Groups(1).Value)
      Return stepN >= 1 AndAlso stepN <= max
    End If
    Dim n As Integer
    If Integer.TryParse(f, n) Then Return n >= min AndAlso n <= max
    Return False
  End Function

  Sub Main()
    Dim cron = "*/5 * * * *"
    Dim p = cron.Split(New Char() {" "c}, StringSplitOptions.RemoveEmptyEntries)
    Dim ok = p.Length = 5 AndAlso
      CheckField(p(0), 0, 59) AndAlso
      CheckField(p(1), 0, 23) AndAlso
      CheckField(p(2), 1, 31) AndAlso
      CheckField(p(3), 1, 12) AndAlso
      CheckField(p(4), 0, 7)
    Console.WriteLine(If(ok, "OK", "INVALID"))
  End Sub
End Module
Explanation

Basic validation in VB.NET to catch out-of-range values.

Notes
  • No ranges/lists.

Related tools

Use the tool when you need to generate or validate output fast.

Trust and privacy

Copy/paste-friendly by design. Still, treat real production secrets carefully.

  • Prefer synthetic examples when sharing screens or recording.
  • Do not paste real API keys, tokens, or personal data unless you fully trust your environment.
  • If you need ordering, do not use UUID v4 as a sortable id: add createdAt or use sortable ids.