Alternations (|
) apply to everything in the surrounding group or globally if not in a group. So in your pattern, the ^
only applies to the first pattern and the $
only applies to the last pattern. In other words, your pattern matches any string which begins with a digit from 1 to 9, contains a 1 followed by a digit from 0 to 9, or ends with a 2 followed by a digit from 0 to 3.
Try putting the different options in one group:
^([1-9]|1[0-9]|2[0-3])$
Also note, 24-hour time starts at 00:00, so your pattern should look more like this:
^(1?[0-9]|2[0-3])$
Or this, if you need the hour to be 2 digits:
^([01][0-9]|2[0-3])$