253

I want a regexp for matching time in HH:MM format. Here's what I have, and it works:

^[0-2][0-3]:[0-5][0-9]$

This matches everything from 00:00 to 23:59.

However, I want to change it so 0:00 and 1:00, etc are also matched as well as 00:00 and 01:30. I.e to make the leftmost digit optional, to match HH:MM as well as H:MM.

Any ideas how to make that change? I need this to work in javascript as well as php.

Ali
  • 261,656
  • 265
  • 575
  • 769
  • 20
    Actually your original regexp will not match a whole range of valid time values, e.g. 17:00 – David Clarke Apr 22 '13 at 02:07
  • 1
    This works: `^(?:[01]?\d|2[0-3])(?::[0-5]\d){1,2}$` and also catches time values yours doesn't match. – GreatAndPowerfulOz Oct 20 '20 at 17:51
  • @GreatAndPowerfulOz That is correct. Instead of [01] you could write [0-1] for uniformity, but this is not necessary, because e.g. [0-3] is exactly the same as [0123], only shorter. And because we are lazy, we always prefer the shortest variant, so we don't have to write more than absolutely necessary. The saying "time is money" applies here ;-) Also ?:: ensures that only the whole pattern capture something and not every group as I have see in the explanation of this pattern on https://regex101.com/r/YNlvQK/1. So today I've learn something new and therefore improve myself. Thanks alot. – Alexander Behling Mar 31 '23 at 10:10

22 Answers22

487

Your original regular expression has flaws: it wouldn't match 04:00 for example.

This may work better:

^([0-1]?[0-9]|2[0-3]):[0-5][0-9]$
NineToeNerd
  • 307
  • 5
  • 17
Peter O.
  • 32,158
  • 14
  • 82
  • 96
179

Regular Expressions for Time

  • HH:MM 12-hour format, optional leading 0

    /^(0?[1-9]|1[0-2]):[0-5][0-9]$/
    
  • HH:MM 12-hour format, optional leading 0, mandatory meridiems (AM/PM)

    /((1[0-2]|0?[1-9]):([0-5][0-9]) ?([AaPp][Mm]))/
    
  • HH:MM 24-hour with leading 0

    /^(0[0-9]|1[0-9]|2[0-3]):[0-5][0-9]$/
    
  • HH:MM 24-hour format, optional leading 0

    /^([0-9]|0[0-9]|1[0-9]|2[0-3]):[0-5][0-9]$/
    
  • HH:MM:SS 24-hour format with leading 0

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

Reference and Demo

Niket Pathak
  • 6,323
  • 1
  • 39
  • 51
  • 1
    Any reason **HH:MM 24-hour with leading 0** is not `^([0-2][0-3]|[0-1][0-9]):[0-5][0-9]+$`? – Vlad Macovei Dec 16 '18 at 20:16
  • Because the regex in the answer works well. And the one you commented works too. Feel free to use either of them. :) – Niket Pathak Dec 18 '18 at 10:02
  • For people matching 12 hours (with am/pm) strings with the above regex, keep in mind that testing "13:00 PM" against the regex will return true (some values) because "3:00 PM" part in the string is valid. I resolved the issue by using the following if statement let res = value.match(regex); if (res && res[0] === value) doSomething(); – Taha Rehman Siddiqui Oct 07 '19 at 17:55
  • does the trailing `\d` in the first example belong there? seems like that would only match 3-digit minutes. – Erich Oct 15 '20 at 17:14
  • yep, you are right. it should be either `[0-9]` or `\d` but not both to avoid matching 3 digit minutes. Answer is updated. – Niket Pathak Oct 16 '20 at 09:06
  • Why not simply `^([0-1][0-9]|2[0-3]):[0-5][0-9]$` for HH:MM 24 hour with leading 0? I mean, why do we need `0[0-9]|1[0-9]` instead of `[0-1][0-9]` there? – String.Empty Dec 02 '20 at 04:01
  • With regex, there are multiple ways to get the same results. Feel free to use whichever seems the easiest/most readable to you ;) – Niket Pathak Dec 03 '20 at 14:56
  • @VladMacovei your answer is not working for me try: 14:000 it matches the regex (at least in python 3.7.12 using re library). – dantebarba Nov 29 '21 at 17:53
  • 1
    @dantebarba I've tried it on regex101.com and it works. The outcome depends on the initial string. if you are searching in a longer string and want to extract a valid hour somewhere in the middle try `([0-2][0-3]|[0-1][0-9]):([0-5][0-9]{1})`. I think i used the previous regex to validate a imput box and that is why i used `^` (starts with) and `$` (ends with). I highly recommend using a regex playground to try out expressions. – Vlad Macovei Nov 30 '21 at 18:52
  • what if I have the time format between more words? like *time is **12:34** is rainy* outside – theboshy Feb 15 '22 at 20:04
  • Its quite simple, you only need to only remove the start/end of string regex (i.e. `(0[0-9]|1[0-9]|2[0-3]):[0-5][0-9]`). Tested for HH:MM 24-hour with leading 0 – Niket Pathak Feb 16 '22 at 14:48
  • Please don't make everything in your answer bold text. – Michael M. Dec 05 '22 at 02:59
  • @MichaelM. thank you for your suggestion. I would like to kindly decline it since I prefer leaving the title in bold for better visibility/readability. Good day :) – Niket Pathak Dec 05 '22 at 10:26
  • What about 24:00, not valid or just 24 hours in a day? Of course equals the next day at 00:00. – Harm Feb 06 '23 at 17:41
  • @Harm, AFAIK, 24:00 is not valid. After 23:59, you get 00:00 which represents the beginning of the next day (you are right to say that 24:00 == 00:00), but in programming, we use only 00:00 to denote the end of the current day as well as the beginning of the next day. – Niket Pathak Feb 07 '23 at 21:49
56

None of the above worked for me. In the end I used:

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

Logic:

The first number (hours) is either: a number between 0 and 19 --> [0-1]?[0-9] (allowing single digit number)
or
a number between 20 - 23 --> 2[0-3]

the second number (minutes) is always a number between 00 and 59 --> [0-5][0-9] (not allowing a single digit)

Roopendra
  • 7,674
  • 16
  • 65
  • 92
Tomer
  • 561
  • 4
  • 2
11

You can use this one 24H, seconds are optional

^([0-1]?[0-9]|[2][0-3]):([0-5][0-9])(:[0-5][0-9])?$
Mike Szyndel
  • 10,461
  • 10
  • 47
  • 63
Bahman Khalafi
  • 121
  • 2
  • 4
6

The best would be for HH:MM without taking any risk.

^(0[0-9]|1[0-9]|2[0-3]):[0-5][0-9]$
Soner Gönül
  • 97,193
  • 102
  • 206
  • 364
Nikhil Rawat
  • 71
  • 1
  • 1
5

Amazingly I found actually all of these don't quite cover it, as they don't work for shorter format midnight of 0:0 and a few don't work for 00:00 either, I used and tested the following:

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

You can use this regular expression:

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

If you want to exclude 00:00, you can use this expression

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

Second expression is better option because valid time is 00:01 to 00:59 or 0:01 to 23:59. You can use any of these upon your requirement. Regex101 link

clinton3141
  • 4,751
  • 3
  • 33
  • 46
Ved
  • 11,837
  • 5
  • 42
  • 60
  • The first expression does not accept 00: **05** . But thanks. Leads me to the validation I was looking for. – JazZ Feb 03 '17 at 18:49
2

As you asked the left most bit optional, I have done left most and right most bit optional too, check it out

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

It matches with

0:0 
00:00
00:0 
0:00
23:59
01:00
00:59

The live link is available here

Ananda G
  • 2,389
  • 23
  • 39
2

Description

hours:minutes with:

  • Mandatory am|pm or AM|PM
  • Mandatory leading zero 05:01 instead of 5:1
  • Hours from 01 up to 12
  • Hours does not accept 00 as in 00:16 am
  • Minutes from 00 up to 59

01:16 am
01:16 AM
01:16 ❌ (misses am|pm)
01:16 Am❌ (am must all be either lower or upper case)
1:16 am ❌ (Hours misses leading zero)
00:16 ❌ (Invalid hours value 00)

Regular Expression

To match single occurrence:
^(0[1-9]|1[0-2]):([0-5][0-9]) ((a|p)m|(A|P)M)$

To match multiple occurrences:
Remove ^ $
(0[1-9]|1[0-2]):([0-5][0-9]) ((a|p)m|(A|P)M)

Saleh Rezq
  • 193
  • 1
  • 13
1

None of the above answers worked for me, the following one worked.

"[0-9]{2}:[0-9]{2}"
aslamhossin
  • 1,217
  • 12
  • 22
1

To validate 24h time, use:

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

This accepts:

22:10
2:10
2/1
...

But does not accept:

25:12
12:61
...
tdy
  • 36,675
  • 19
  • 86
  • 83
0

You can use following regex:

^[0-1][0-9]:[0-5][0-9]$|^[2][0-3]:[0-5][0-9]$|^[2][3]:[0][0]$
Basavaraj
  • 1,081
  • 1
  • 11
  • 21
0

The below regex will help to validate hh:mm format

^([0-1][0-9]|2[0-3]):[0-5][0-9]$
Ankit
  • 760
  • 6
  • 15
0

Declare

private static final String TIME24HOURS_PATTERN = "([01]?[0-9]|2[0-3]):[0-5][0-9]:[0-5][0-9]";

public boolean validate(final String time) {
    pattern = Pattern.compile(TIME24HOURS_PATTERN);
    matcher = pattern.matcher(time);
    return matcher.matches();
}

This method return "true" when String match with the Regular Expression.

Renats Stozkovs
  • 2,549
  • 10
  • 22
  • 26
0

A slight modification to Manish M Demblani's contribution above handles 4am (I got rid of the seconds section as I don't need it in my application)

^(([0-1]{0,1}[0-9]( )?(AM|am|aM|Am|PM|pm|pM|Pm))|(([0]?[1-9]|1[0-2])(:|\.)[0-5][0-9]( )?(AM|am|aM|Am|PM|pm|pM|Pm))|(([0]?[0-9]|1[0-9]|2[0-3])(:|\.)[0-5][0-9]))$

handles: 4am 4 am 4:00 4:00am 4:00 pm 4.30 am etc..

JonathanDavidArndt
  • 2,518
  • 13
  • 37
  • 49
Bob Light
  • 31
  • 4
0

Your code will not work properly as it will not work for 01:00 type formats. You can modify it as follows.

pattern =r"^(0?[1-9]|1[0-2]):[0-5][0-9]$"

Making it less complicated we can use a variable to define our hours limits.Further we can add meridiems for more accurate results.

hours_limit = 12 
pattern = r"^[1-hours_limit]:[0-5][0-9]\s?[AaPp][Mm]$"
print(re.search(pattern, "2:59 pm"))
0

Check this one

/^([0-1]?[0-9]|2[0-3]):([0-5]?[0-9]|5[0-9])$/
Ishara Samintha
  • 460
  • 6
  • 8
-1

Mine is:

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

This is much shorter

Got it tested with several example

Match:

  • 00:00
  • 7:43
  • 07:43
  • 19:00
  • 18:23

And doesn't match any invalid instance such as 25:76 etc ...

-1

check this masterfull timestamp detector regex I built to look for a user-specified timestamp, examples of what it will pickup include, but is most definitely NOT limited to;

8:30-9:40
09:40-09 : 50
09 : 40-09 : 50
09:40 - 09 : 50
08:00to05:00
08 : 00to05 : 00
08:00 to 05:00
8am-09pm
08h00 till 17h00
8pm-5am
08h00,21h00
06pm untill 9am

It'll also pickup many more, as long as the times include digits

pythonian29033
  • 5,148
  • 5
  • 31
  • 56
  • 1
    `RegExr requires a modern browser. Please update your browser to the latest version and try again.` ... I can't even see it ... :-/ – Martin Tournoij Jul 17 '14 at 15:09
  • I re-wrote this a tiny bit using non-capturing groups to make matches easier to isolate. https://regex101.com/r/424USF/1 '/(\d{1,2}\s{0,2}(?:am|pm|(?:[-|:|h| ]\s{0,2}\d{1,2}\s{0,2})?)\s{0,2})(-|to|till|,|until)(\s{0,2}\d{1,2}\s{0,2}(?:am|pm|(?:[-|:|h| ]\s{0,2}\d{1,2}\s{0,2})?))/gmi' – Joel Mellon Feb 17 '23 at 18:40
-1

You can try the following

^\d{1,2}([:.]?\d{1,2})?([ ]?[a|p]m)?$

It can detect the following patterns :

2300 
23:00 
4 am 
4am 
4pm 
4 pm
04:30pm 
04:30 pm 
4:30pm 
4:30 pm
04.30pm
04.30 pm
4.30pm
4.30 pm
23:59 
0000 
00:00
Manish M Demblani
  • 910
  • 1
  • 10
  • 21
-3

Try the following

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

Note: I was assuming the javascript regex engine. If it's different than that please let me know.

JaredPar
  • 733,204
  • 149
  • 1,241
  • 1,454
-3

You can use following regex :

^[0-2]?[0-3]:[0-5][0-9]$

Only modification I have made is leftmost digit is optional. Rest of the regex is same.

Shekhar
  • 11,438
  • 36
  • 130
  • 186