First, define a pattern that matches a single point in time. Given your examples it might be something like:
(noon|midnight|[0-9]+\s?(am|pm)?)
Next, define the separator. Perhaps:
(to|\-)
Finally, combine two of the first with one of the second. Assuming your language supports variables, something like:
set timePattern {(noon|midnight|[0-9]+\s?(am|pm)?)}
set separator {(to|\-)}
set fullPattern "$timePattern(\s*$separator\s*$timePattern)?"
Once you pass that through the engine you should be able to get at the parts of the expression that matched. You might need to make some groups non-capturing but I'll leave that as an exercise for the reader. You'll then likely have to parse the individual parts to figure out the time. For example, parse "1pm" as a 1 and "pm" and calculate a time based on that.
Once you have it broken down like that it makes it easier to fiddle with the constituent parts and makes the expression a bit more comprehensible. Though, the same thing can be accomplished in some languages that support multiline expressions with comments.