Based on the Charles's elegant answer with regular expression. If you need a one line validation of both "HH:MM"
and "H:MM"
(i.e. "9:45"
/"09:45"
) use the following regexp to match 24-hour format:
preg_match("/^(?(?=\d{2})(?:2[0-3]|[01][0-9])|[0-9]):[0-5][0-9]$/", $time)
Explanation
(?
stands for conditional subpattern, the syntax is:
(?(condition)yes-pattern|no-pattern)
?=
in condition is the regexp assertion
?:
in yes-pattern is optional for better performance and you may drop it. This means we don't need any capturing within parentheses ()
, we need just alternatives feature.
So, we merely describe the following:
- If
$time
string begins with two digits (?=\d{2})
, use (2[0-3]|[01][0-9])
pattern to match HH-hour notation ("09:45"
case)
- otherwise use
[0-9]
pattern to match H-hour notation ("9:45"
case)
UPDATE
As they say, simplicity is the sister of a talent. We don't necessarily need the condition pattern described above. The simpler validation of "HH:MM/H:MM"
for 24-hour format:
preg_match("/^(?:2[0-3]|[01][0-9]|[0-9]):[0-5][0-9]$/", $time)
Again, ?:
in grouping parentheses ()
is optional to disable capturing, you can drop it.
So, in this regexp the alternative subpatterns withing ()
is trying to match two digits hour at the first (20..23
) and second (01..19
) pattern, then one digit at the last third one (0..9
).
In addition, the validation of "HH:MM/H:MM"
for 12-hour format:
preg_match("/^(?:0?[1-9]|1[012]):[0-5][0-9]$/", $time);
Here, we're trying to match at first one digit (1..9
) with possible preceding zero (0?
), and then two digits (10..12
).