0

I have a regex to parse ISO8601 times, and it tests beautifully in RegexBuddy, but when I run it in JavaScript, either using jsbin.com or my Node.js program, the last value passes when it should fail (12:30.05 PM).

It seems to think the second : is ok with a .

I have tried specifying \:, [:] and other variations, but in JavaScript it always returns true.

Anybody seen this behavior before?

var vals = [
  '04:05:06.789',
  '05:05:06',
  '04:05',
  '040506',
  '04:05 AM',
  '04:05 PM',
  '04:05:06.789-8',
  '04:05:06-08:00',
  '04:05-08:00',
  '04:05-08',
  '04:05:06 PST',
  '04:05:06 America/New_York',
  '12:30.05 PM'
];

vals.forEach(val => {
  console.log(/^[01][0-9]:?[0-5][0-9](:?([0-5][0-9])((\.)?(\d{0,14})?)?)?(\s[AaPp][Mm])?(([+-]\d{1,2}(:[0-2][0-9])?)|(\s(\w)+)|((\w)+\/(\w)+)|())?/.test(val))
});
John M
  • 111
  • 1
  • 1
  • 7

1 Answers1

1

You didn’t specify an ending anchor, so it’s just matching the beginning of your last example: 12:30.

Add a $:

var vals = [
  '04:05:06.789',
  '05:05:06',
  '04:05',
  '040506',
  '04:05 AM',
  '04:05 PM',
  '04:05:06.789-8',
  '04:05:06-08:00',
  '04:05-08:00',
  '04:05-08',
  '04:05:06 PST',
  '04:05:06 America/New_York',
  '12:30.05 PM'
];

vals.forEach(val => {
  console.log(/^[01][0-9]:?[0-5][0-9](:?([0-5][0-9])((\.)?(\d{0,14})?)?)?(\s[AaPp][Mm])?(([+-]\d{1,2}(:[0-2][0-9])?)|(\s(\w)+)|((\w)+\/(\w)+)|())?$/.test(val))
});

Looking just at the working regex, now:

/^[01][0-9]:?[0-5][0-9](:?([0-5][0-9])((\.)?(\d{0,14})?)?)?(\s[AaPp][Mm])?(([+-]\d{1,2}(:[0-2][0-9])?)|(\s(\w)+)|((\w)+\/(\w)+)|())?$/

Make it case-insensitive to avoid [AaPp] and the like:

/^[01][0-9]:?[0-5][0-9](:?([0-5][0-9])((\.)?(\d{0,14})?)?)?(\s[AP]M)?(([+-]\d{1,2}(:[0-2][0-9])?)|(\s(\w)+)|((\w)+\/(\w)+)|())?$/i

Remove unnecessary groups (some might be necessary, but (\w)+ as opposed to (\w+) will never be useful):

/^[01][0-9]:?[0-5][0-9](:?[0-5][0-9](\.?(\d{0,14})?)?)?(\s[AP]M)?([+-]\d{1,2}(:[0-2][0-9])?|\s\w+|\w+\/\w+|)?$/i

Remove unnecessary ?s on patterns that already match empty strings, like \d{0,14}:

/^[01][0-9]:?[0-5][0-9](:?[0-5][0-9](\.?\d{0,14})?)?(\s[AP]M)?([+-]\d{1,2}(:[0-2][0-9])?|\s\w+|\w+\/\w+)?$/i

Use \d consistently, since it’s exactly equivalent to [0-9] in JavaScript:

/^[01]\d:?[0-5]\d(:?[0-5]\d(\.?\d{0,14})?)?(\s[AP]M)?([+-]\d{1,2}(:[0-2]\d)?|\s\w+|\w+\/\w+)?$/i
Ry-
  • 218,210
  • 55
  • 464
  • 476