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.
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.
| Token | Meaning |
|---|---|
| ^ | 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]\d | Minutes 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.
Test Cases
Editable — add your own inputs to see if they pass.
| Input | Expected | Result | |
|---|---|---|---|
| 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")); // trueCommon 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
| Engine | Supported | Notes |
|---|---|---|
| Chrome | Yes | — |
| Firefox | Yes | — |
| Safari | Yes | — |
| Edge | Yes | — |
| Node.js | Yes | — |