48

I would like a JavaScript regular expression that will match time using the 24 hour clock, where the time is given with or without the colon.

For example, I would like to match time in the following formats:

  • 0800
  • 23:45
  • 2345

but that would not match invalid times such as

  • 34:68
  • 5672
Alan Moore
  • 73,866
  • 12
  • 100
  • 156
rswolff
  • 3,258
  • 5
  • 28
  • 31

15 Answers15

133

This should do it:

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

The expression reads:

^        Start of string (anchor)
(        begin capturing group
  [01]   a "0" or "1"
  \d     any digit
 |       or
  2[0-3] "2" followed by a character between 0 and 3 inclusive
)        end capturing group
:?       optional colon
(        start capturing
  [0-5]  character between 0 and 5
  \d     digit
)        end group
$        end of string anchor
Greg
  • 316,276
  • 54
  • 369
  • 333
  • 7
    24:00 doesn't exist but is matched. Change `[0-4]` to `[0-3]`. – strager Sep 29 '09 at 20:20
  • or in the form: ^(([0-9])|([0-1][0-9])|([2][0-3])):?([0-5][0-9])$ if you do not like the \d stuff :) – Mark Schultheiss Sep 29 '09 at 20:54
  • 9
    strager: 24:00 is perfectly valid, referring to the exact *end* of a day (and technically being the next day at 0:00). See http://en.wikipedia.org/wiki/24_hour_time#Midnight_00:00_and_24:00 – Joey Sep 30 '09 at 05:46
  • @strager—nor do 12pm and 12am, but people keep usint them… ;-) – RobG Oct 22 '15 at 23:17
  • Human friendly equivalent would be: `^([0-1][0-9]|2[0-3]):?([0-5][0-9])$` – Leonard Jul 29 '21 at 05:38
12
/(00|01|02|03|04|05|06|07|08|09|10|11|12|13|14|15|16|17|18|19|20|21|22|23):?(0|1|2|3|4|5)\d/

:)

Zed
  • 57,028
  • 9
  • 76
  • 100
8

Here is a better solution than the top one above for military plus a civilian solution.

Military

^(((([0-1][0-9])|(2[0-3])):?[0-5][0-9])|(24:?00))

I believe the or in the highest rated response is not properly parsing the subsets before and after without the extra set of parenthesis to group them. Also, I'm not certain that the \d is just 0-9 in all iterations. It technically includes the special [[:digit:]] although I've never dealt with that being an issue before. Any how, this should provide every thing including the crossover 2400/24:00

Civilian

^([0-9]|([1][0-2])):[0-5][0-9][[:space:]]?([ap][m]?|[AP][M]?)

This is a nice Civilian version that allows for the full range formatted like 12:30PM, 12:30P, 12:30pm, 12:30p, 12:30 PM, 12:30 P, 12:30 pm, or 12:30 p but requires the morning or post meridian characters to be the same case if both are included (no Am or pM).

I use both of these in a bit of JavaScript to validate time strings.

user247702
  • 23,641
  • 15
  • 110
  • 157
Robert Bolin
  • 81
  • 2
  • 3
  • Thanks, I like this one. I did add the $ at the end of it though. Also, I made the 0 optional at the beginning (i.e. 01:25 could be 1:25). Hopefully didn't mess anything up along the way. ^(((([0-1]?[0-9])|(2[0-3])):?[0-5][0-9])|(24:?00))$ – nardnob Feb 18 '16 at 16:29
  • The civilian one doesn't seem to work. If you throw it into http://regexr.com/ and try 12:30p, it returns no matches. – ThePersonWithoutC May 03 '16 at 21:06
  • Works fine in regex101.com. Perhaps you misryped it instead of copy/paste? Regexr.com doesn't work on mobile devices or I would check. – Robert Bolin May 07 '16 at 13:11
  • There is no limit on the end of the regex, it will allow other characters to be entered at the end and still match, eg 13:4502938 – Japheth Ongeri - inkalimeva Nov 10 '16 at 08:36
2

To keep the colon optional and allow all valid times:

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

Note that this assumes midnight will always be 0000 and never 2400.

DocMax
  • 12,094
  • 7
  • 44
  • 44
0

This is the one I've just come up with:

(^((2[0-4])|([01]?[0-9])):[0-5][0-9]$)|(^((1[0-2])|(0?[1-9])(:[0-5][0-9])?)[pa]m$)

Accepts:

2pm
4:30am
07:05am
18:45
6:19
00:55

does not accept 00:05am - I am not sure if there is such time as 0am

If you feel that : is optional for 24h time format (military) - just add a question mark after it

Hassan Imam
  • 21,956
  • 5
  • 41
  • 51
PaulG
  • 154
  • 5
0

Here's a blog post, looking for the same thing and a bunch of potential answers -- most of which don't work, but there is good discussion as to why each fails.

Of course, explicitly long and accurate is always a possibility!

Community
  • 1
  • 1
Michael Paulukonis
  • 9,020
  • 5
  • 48
  • 68
  • Yeah, he could just generate all possible times to an array (should be less than 16k), and then it is just a comparison =) – Zed Sep 29 '09 at 20:27
0

I know this is an old question but here's a regex I came up with which seems to work.

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

You can edit it on this regex site

Edit I just realised that this answer ended up exactly the same as the accepted answer but I will leave it here at least for the value of the 'do it yourself' link

0

This is perfect:

^0?([0-9][0-2]?):[0-5][0-9]$

Note: 12 Hr Clock Only

For Times like:

0:01- 12:59
00:01 - 12:59
Hassan Imam
  • 21,956
  • 5
  • 41
  • 51
Byorn
  • 681
  • 8
  • 5
0

A human friendly version:

^([0-1][0-9]|2[0-3]):?([0-5][0-9])$

Leonard
  • 2,978
  • 6
  • 21
  • 42
0

I've done this slightly differently to avoid the possibility of a single zero leading the time, like 0:45 vs 00:45. From what I can see, the more commonly used format allows for this technically incorrect format. Mine also prevents pattern matches in trailing characters, as others have done.

\b^(0?[1-9]|[0-1][0-9]|2[0-3]):([0-5][0-9])(:[0-5][0-9])?$
Laurie
  • 11
  • 3
0

This regex will also pass for when leading zero is not there. Example: 1:11:11

(0?[0-9]|[0-1][0-9]|2[0-3]):([0-5]\d):([0-5]\d))
z atef
  • 7,138
  • 3
  • 55
  • 50
0

Try this i think this is the best regex

data-inputmask-regex="^([0-1][0-9]|[2][0-3]):[0-5][0-9]$"
-1
/^(?:[01]\d|2[0-3]):?[0-5]\d$/
Jeremy Stein
  • 19,171
  • 16
  • 68
  • 83
-1

I don't think regex is the right solution for this problem. Sure, it COULD be done, but it just seems wrong.

Make sure your string is four characters long, or 5 characters with a colon in the middle. Then, parse each side and make sure that the left side is less than 24 and the right hand is less than 60.

The regex solution is just so much more complicated.

Stefan Kendall
  • 66,414
  • 68
  • 253
  • 406
  • 1
    Have you not read the other posts? There were numerous attempts, and barely ANYONE got the solution correct (or even understood the problem entirely). My solution is pretty hard to mess up in any language or implementation. – Stefan Kendall Sep 29 '09 at 20:32
  • 2
    Oh, there are plenty of ways to mess up your solution, too. Especially if you're trying to type fast like we were. – Jeremy Stein Sep 29 '09 at 20:54
  • Plenty of WAYS to mess it up? Sure. Easy to mess up? No. Easy to spot a mistake? Yes. Regex? No. – Stefan Kendall Sep 29 '09 at 21:18
-1

Remove the ':' if the string has one, then if the string is of the form "DDDD", convert it into an int and compare it to 2400.

David R Tribble
  • 11,918
  • 5
  • 42
  • 52