javascriptregexlookbehind

Rewrite regex without positive look-behind


I have the following regex that uses look-behind to match different time formats inside a string:

(?:(?<=[\s])|^)(2[0-3]|[01]?[0-9]):([0-5]?[0-9])(?::([0-5]?[0-9]))?( ?[AP]M)?(?:(?=[\s])|$)

The regex must match 12-hour or 24-hour time formats, with minutes and optional seconds. Examples:

10:00 AM
Time: 10:00 (only the `10:00` part)
13:23:34

The regex should entirely reject the following strings:

hello10:00 (the time is not separated by whitespace)
24:00:00 (24 does not make sense)
9912:1299 (there's a time substring, but the whole string is not really a time).

I'm trying to rewrite it to not use positive look-behind, which is not supported by every web browser. How could I do it?


Solution

  • const rgx = /\b(?:1?\d|2[0-3]):[0-5]\d(?::[0-5]\d)? ?(?:[ap]m)?\b/gi;
    
    Segment Description
    \b to the left is a non-word and to the right is a word
    (?:1?\d begin non-capturing group 0 to 19
    | OR
    2[0-3]) 20 to 23 end non-capturing group
    :[0-5]\d : 00 to 59
    (?::[0-5]\d)? ? same as above with a space or nothing
    (?:[ap]m)? a or p then m or nothing
    \b to the right is a non-word and to the left is a word

    const rgx = /\b(?:1?\d|2[0-3]):[0-5]\d(?::[0-5]\d)? ?(?:[ap]m)?\b/gi
    
    const str = `
    10:00 AM
    Time: 10:00
    13:23:34
    hello10:00
    24:00:00
    9912:1299`;
    
    const res = [...str.matchAll(rgx)].flat();
    
    console.log(res);