★ Dev formats · regex
Regex for 24-hour Time
Matches two-digit 24-hour times with optional seconds. Leap seconds and 24:00 are rejected.
- Runs in your browser
- No signup
Try the 24-hour time pattern
Read it in plain English (best-effort)
- ^start of a line
- (?:start a group (not captured)
- [01]one character from: '0', '1'
- \da digit (0–9)
- |or
- 2the character '2'
- [0-3]one character from: 0–3
- )end of group
- :the character ':'
- [0-5]one character from: 0–5
- \da digit (0–9)
- (?:start a group (not captured)
- :the character ':'
- [0-5]one character from: 0–5
- \da digit (0–9)
- )end of group
- ?the previous is optional
- $end of a line
One sample per line works well with the m flag on anchored patterns.
The pattern, piece by piece
/^(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d)?$/| Part | What it does |
|---|---|
(?:[01]\d|2[0-3]) | hours 00–23 |
:[0-5]\d | minutes 00–59 |
(?::[0-5]\d)? | optional seconds 00–59 |
What it accepts and rejects
Every sample below is checked automatically in JavaScript and Python. The tester above is preloaded with all of them, one per line.
| Should match | |
|---|---|
00:00 | ✓ |
09:30 | ✓ |
23:59 | ✓ |
12:00:00 | ✓ |
18:45:59 | ✓ |
07:05 | ✓ |
| Should not match | |
|---|---|
24:00 | ✗ |
9:30 | ✗ |
12:60 | ✗ |
12:30:60 | ✗ |
12:30 PM | ✗ |
1230 | ✗ |
Copy it into your code
RE2-safeNo lookarounds or backreferences, so the same pattern works in Go's RE2 engine and in Rust's regex crate.
const time24hRe = /^(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d)?$/;
export function isValidTime24h(value) {
return time24hRe.test(value.trim());
}When not to use regex for this
If users pick times, use a time input (<input type="time">) instead of free text; the browser enforces the format for you.
Questions engineers actually ask
Does it accept single-digit hours like 9:30?
Is 24:00 valid?
What is catastrophic backtracking?
More dev formats patterns
- UUIDRFC 9562 UUIDs, versions 1–8, with the standard variant bits.^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$
- ISO 8601 DateYYYY-MM-DD dates with valid month and day ranges. Format only.^\d{4}-(?:0[1-9]|1[0-2])-(?:0[1-9]|[12]\d|3[01])$
- Semantic VersionThe official semver.org pattern, with pre-release and build metadata.^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$
- JWTThree base64url segments starting with eyJ. Shape only, never trust it.^eyJ[A-Za-z0-9_-]*\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]*$
- Base64Standard padded base64: groups of four with = or == padding.^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$
- MAC AddressColon, hyphen or Cisco dot notation, without mixing separators.^(?:(?:[0-9A-Fa-f]{2}:){5}[0-9A-Fa-f]{2}|(?:[0-9A-Fa-f]{2}-){5}[0-9A-Fa-f]{2}|(?:[0-9A-Fa-f]{4}\.){2}[0-9A-Fa-f]{4})$
Or browse the full regex library.
More from the workbench
Fine print
Tools: on the house.
Engineer: by the hour.
The regex was free. Code that doesn't need one is the upgrade: typed schemas, validated once at the edge, trusted everywhere after.
I'm Himanshu, an AI and full-stack engineer. I build MVPs, AI agents and the growth plumbing around them for early-stage startups.
