/^/
MediumDates4 min read

ISO 8601 Time Regex

Validates a 24-hour ISO 8601 time-of-day string in HH:MM:SS format, with an optional fractional-seconds component of up to three digits.

#time#iso8601#validation#dates#clock

Regex Pattern

^([01]\d|2[0-3]):[0-5]\d:[0-5]\d(\.\d{1,3})?$

Pattern Breakdown

Hover over a token to see what it does.

^([01]\d|2[0-3]):[0-5]\d:[0-5]\d(\.\d{1,3})?$
TokenMeaning
^Anchors the match to the start of the string.
([01]\d|2[0-3])The hour: 00-19 or 20-23.
:A literal colon separating hour, minute, and second.
[0-5]\dMinutes or seconds: 00-59.
(\.\d{1,3})?Optional fractional seconds, 1 to 3 digits, preceded by a dot.
$Anchors the match to the end of the string.

Detailed Explanation

What it does

This pattern matches the time portion of an ISO 8601 timestamp, such as 14:30:00 or 23:59:59.999. It requires a zero-padded 24-hour hour, minute, and second, and optionally allows up to three digits of fractional-second precision.

Why it works

The hour group `([01]\d|2[0-3])` covers 00-19 with the first alternative and 20-23 with the second, correctly excluding 24 and above. Minutes and seconds reuse the same `[0-5]\d` class since both range 00-59. The optional group `(\.\d{1,3})?` is anchored by the trailing `$`, so a fractional part with the wrong number of digits, or a trailing dot with no digits, causes the whole match to fail rather than partially matching.

Common use cases

  • Validating a time input field before combining it with a date for an API payload
  • Pre-checking log timestamps that embed an ISO time component
  • Sanity-checking user-entered appointment or schedule times
  • Filtering structured text for well-formed 24-hour time strings

Edge cases

  • 23:59:59.999 matches with three fractional digits, the maximum this pattern allows
  • 24:00:00, sometimes used to mean end-of-day, correctly fails since hours only go up to 23
  • 12:30:00.1234 fails because four fractional digits leave a dangling digit before the end anchor
  • A trailing dot with no digits, like 12:30:00., correctly fails since the fractional group requires at least one digit when present

Limitations

  • Does not support timezone designators like Z or +02:00, only the bare time-of-day
  • Does not validate 12-hour AM/PM formatted times
  • Cannot verify that a time is meaningful in context (e.g. business hours), only that it's well-formed

Interactive Tester

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

00:00:00 23:59:59 23:59:59.999

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 isoTimePattern = /^([01]\d|2[0-3]):[0-5]\d:[0-5]\d(\.\d{1,3})?$/;

function isValidIsoTime(value) {
  return isoTimePattern.test(value);
}

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

Common Mistakes

Using `\d{2}` for the hour, which incorrectly accepts hours like 25 or 99.

Fix: Split the hour into two alternatives, `[01]\d|2[0-3]`, so only 00-23 is accepted.

Forgetting to anchor with `^` and `$`, allowing a valid time to match inside a longer, malformed string.

Fix: Always anchor the full pattern so the entire string must represent a valid time.

Assuming this pattern also validates timezone offsets like Z or +05:30.

Fix: Extend the pattern with an optional trailing group such as `(Z|[+-]([01]\d|2[0-3]):[0-5]\d)?` if timezone support is needed.

Performance Notes

  • All quantifiers are bounded, so the engine matches in linear time with no catastrophic backtracking risk.
  • Anchoring both ends lets malformed input fail fast without scanning the rest of the string.
  • The optional fractional-seconds group is checked last, so well-formed HH:MM:SS strings without a fraction match with minimal extra work.

Browser Compatibility

EngineSupportedNotes
ChromeYes
FirefoxYes
SafariYes
EdgeYes
Node.jsYes