I will explain by writing the regex in extended mode, which permits comments:
r = /
^ # match the beginning of the string
( # begin capture group 1
1 # match 1
[0-2] # match one of the characters 0,1,2
| # or
0? # optionally match a zero
[1-9] # match one of the characters between 1 and 9
) # end capture group 1
: # match a colon
( # begin capture group 2
[0-5] # match one of the characters between 0 and 5
[0-9] # match one of the characters between 0 and 9
) # end capture group 2
( # begin capture group 3
\s # match one whitespace character
[A|P] # match one of the characters A, | or P
M # match M
) # end capture group 3
\)? # optionally match a right parenthesis
$ # match the end of the string
/x # extended mode
As noticed by @Mischa, [A|P]
is incorrect. It should be [AP]
. That's because "|"
is just an ordinary character when it's within a character class.
Also, I think the regex would be improved by moving \s
out of capture group 3. We therefore might write:
r = /^(1[0-2]|0?[1-9]):([0-5][0-9])\s([AP]M)\)?$/
It could be used thusly:
result = "11:39 PM" =~ r
if result
puts "It's #{$2} minutes past #{$1}, #{ $3=='AM' ? 'anti' : 'post' } meridiem."
else
# raise exception?
end
#=> It's 39 minutes past 11, post meridiem.
In words, the revised regex reads as follows:
- match the beginning of the string.
- match
"10"
, "11"
, "12"
, or one of the digits "1"
to "9"
, optionally preceded by a zero, and save the match to capture group 1.
- match a colon.
- match a digit between
"0"
and "5"
, then a digit between "0"
and "9"
, and save the two digits to capture group 2.
- match a whitespace character.
- match
"A"
, or "P"
, followed by "M"
, and save the two characters to capture group 3.
- optionally match a right parenthesis.
- match the end of the string.