/^/
EasyDates4 min read

24-Hour Time Regex

Validates a 24-hour clock time in HH:MM or HH:MM:SS format, such as 09:30 or 23:59:59.

#time#24-hour#validation#dates#clock

Regex Pattern

^([01]\d|2[0-3]):([0-5]\d)(:([0-5]\d))?$

Pattern Breakdown

Hover over a token to see what it does.

^([01]\d|2[0-3]):([0-5]\d)(:([0-5]\d))?$
TokenMeaning
([01]\d|2[0-3])The hour: 00-19 or 20-23.
:A literal colon separating hours, minutes, and seconds.
([0-5]\d)The minutes: 00-59.
(:([0-5]\d))?An optional colon-separated seconds group, also 00-59.
^Anchors the match to the start of the string.
$Anchors the match to the end of the string.

Detailed Explanation

What it does

This pattern matches times expressed on a 24-hour clock, with hours ranging from 00 to 23, minutes from 00 to 59, and an optional seconds component also from 00 to 59. It accepts both HH:MM and HH:MM:SS forms.

Why it works

The hour group `([01]\d|2[0-3])` splits the valid range into 00-19 (any digit after 0 or 1) and 20-23 (a stricter range after 2), which together cover exactly 00-23. Minutes and seconds both use `[0-5]\d`, since the tens digit of a valid minute or second can only be 0-5. Wrapping the seconds portion, colon included, in an optional group `(...)?` lets the same pattern accept times with or without seconds.

Common use cases

  • Validating time-of-day input fields in scheduling or booking forms
  • Parsing log timestamps that use a 24-hour clock
  • Checking configuration values like cron-adjacent time windows
  • Client-side validation before combining a time string with a date for a full timestamp

Edge cases

  • Midnight is represented as 00:00, not 24:00, which correctly fails to match
  • Leap seconds (a 60th second) are not representable and correctly fail, e.g. 23:59:60
  • Single-digit hours or minutes without a leading zero, like 9:30, correctly fail to match
  • HH:MM:SS with a trailing fractional second, like 12:00:00.500, is not matched by this pattern alone

Limitations

  • Does not support 12-hour clock notation with AM/PM suffixes
  • Does not support fractional seconds or timezone offsets
  • Does not account for leap seconds (23:59:60), which some systems briefly use

Interactive Tester

Edit the pattern or text below — matching runs live in your browser.

23:59 00:00:00 07:05

Test Cases

Editable — add your own inputs to see if they pass.

InputExpectedResult
Pass
Pass
Pass
Pass
Pass
Pass
Pass
Pass

Language Variants

Production-ready examples in 12 languages.

const timePattern = /^([01]\d|2[0-3]):([0-5]\d)(:([0-5]\d))?$/;

function isValid24HourTime(value) {
  return timePattern.test(value);
}

console.log(isValid24HourTime("23:59:59")); // true

Common Mistakes

Using a naive hour range like [0-2][0-9], which incorrectly allows 24-29.

Fix: Split the hour into two alternatives, `[01]\d|2[0-3]`, so anything from 24 upward is rejected.

Forgetting the seconds group is optional and requiring HH:MM:SS everywhere.

Fix: Wrap the seconds portion, colon included, in `(...)?` so both HH:MM and HH:MM:SS are accepted where appropriate.

Trying to reuse this pattern for 12-hour times with AM/PM.

Fix: Use a dedicated 12-hour pattern like `^(0?[1-9]|1[0-2]):[0-5]\d\s?(AM|PM)$` instead.

Performance Notes

  • All repetition is bounded to single characters or small fixed groups, so there is no catastrophic backtracking risk.
  • The optional seconds group is a small, clearly delimited alternative, so failed attempts to match it backtrack cheaply.
  • Anchors at both ends prevent partial matches inside longer strings, avoiding unnecessary scanning.

Browser Compatibility

EngineSupportedNotes
ChromeYes
FirefoxYes
SafariYes
EdgeYes
Node.jsYes