24-Hour Time Regular Expression – Free, Online, Private
Matches a 24-hour time, HH:MM, with an optional :SS.
- 09:00
- 18:30
- 23:59:59
The pattern
09:00 and 18:30 match. 23:59:59 matches because the seconds group is optional and well formed. 24:00 does not, because the hour stops at 23. 9:00 does not, because the hour must be two digits. There is no AM/PM. Midnight is 00:00. The pattern is the one to use next to a cron hour, which is also a 24-hour number, so the two pages do not disagree about what 18 means.
The source is ^(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d)?$. The flags on this page are m. i means case-insensitive. m means ^ and $ match at line breaks, which is how the sample can show several candidates. g is not set. The tester finds non-overlapping matches, and without g a pattern with no anchor still reports the matches it walks. The box under the title is a tester with this pattern and the sample already filled in. Edit either one. Nothing you type is uploaded. The same tester, without a preset, is the regex tool.
How to read it
(?:[01]\d|2[0-3]) is the hour: 00–19 from the first branch and 20–23 from the second. : is literal. [0-5]\d is the minute, 00–59. (?::[0-5]\d)? is an optional colon and seconds, with the same 00–59 range. Anchors and the m flag test each line. A trailing Z or an offset is not part of this pattern. The ISO datetime pattern is the one that wants a date and a zone.
What it will not do
Leap seconds are not represented. 23:59:60 fails, and a system that emits a leap second will need a special case. The pattern does not accept a single-digit hour. Pad it. It does not accept 24:00 as an end-of-day sentinel. Some business systems use 24:00 to mean the end of the day rather than the next midnight. This pattern treats that as invalid. Fractional seconds are not accepted. Use the datetime pattern for those.
A match is not a parsed value. An email pattern does not send mail, a UUID pattern does not allocate an id, and a password pattern does not store a password. When the next step needs a real parser, use one: the URL constructor, a date library, a semver library, or the converters on this site. The expression is the part you can see.
JavaScript, Python, and Go
The JavaScript snippet uses the RegExp constructor so the source does not have to be escaped for a literal slash. The Python snippet uses a normal string with the same escapes JSON would emit, which keeps \d as a regex digit class. Go's snippet uses a raw string. If the pattern contains a lookahead, the Go snippet says so and does not call MustCompile, because RE2 would reject it at runtime.
JavaScriptconst re = new RegExp("^(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d)?$", "m");
const found = text.match(re);
console.log(found ? found[0] : "no match");
Pythonimport re
pattern = re.compile("^(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d)?$", re.MULTILINE)
found = pattern.search(text)
print(found.group(0) if found else "no match")
Gopackage main
import (
"fmt"
"regexp"
)
func main() {
text := ""
re := regexp.MustCompile(`(?m)^(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d)?$`)
fmt.Println(re.FindString(text))
}
Frequently asked questions
Does 24:00 match?
No. Hours run from 00 to 23. Midnight at the start of a day is 00:00.
Are seconds required?
No. HH:MM matches, and :SS is optional.
Does 9:00 match?
No. The hour is two digits. Use 09:00.
Is 18:00 the same as 6 PM?
On a 24-hour clock, yes. Cron hours use the same numbering.