2

I have written regex like below:

/^(\d{4}\-\d\d\-\d\d)|(\d{4}\-\d\d\-\d\d([tT][\d:\.]*){1})([zZ]|([+\-])(\d\d):?(\d\d))?$/.test("1995-01-01")

It is working fine but even if i give wrong format also return true as value please refer below screenshot:

tt

Kumaresan Sd
  • 1,399
  • 4
  • 16
  • 34
  • You did not group the pattern correctly. Try `/^(?:(\d{4}\-\d\d\-\d\d)|(\d{4}\-\d\d\-\d\d([tT][\d:\.]*){1})([zZ]|([+\-])(\d\d):?(\d\d))?)$/` – Wiktor Stribiżew Jun 18 '19 at 09:58
  • @WiktorStribiżew, post this as answer – Kumaresan Sd Jun 18 '19 at 10:00
  • This question is wrongly closed with [this question](https://stackoverflow.com/questions/7388001/javascript-regex-to-validate-date-format) and the fact Ghoul [posted](https://stackoverflow.com/a/56646512/3832970) an (actually irrelevant for the current scenario) answer similar to the ones in that thread does not make it a dupe. The question here is how to use two alternatives in one regex that should match the whole string. – Wiktor Stribiżew Jun 19 '19 at 09:02

2 Answers2

3

Try this:

const regex = /([12]\d{3}-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01])$)/;

console.log(regex.test('1995-01-01')) //true
console.log(regex.test('1995-01-016')) //false

enter image description here

Ghoul Ahmed
  • 4,446
  • 1
  • 14
  • 23
2

The problem with the current regex is that you have two alternations that are each anchored on one side only, the first at the start and the last at the end.

The quick fix would be

^(?:(\d{4}-\d\d-\d\d)|(\d{4}-\d\d-\d\d([tT][\d:.]*))([zZ]|([+-])(\d\d):?(\d\d))?)$
 ^^^                 ^                                                          ^

See this regex demo.

However, since both alternatives start with the same pattern, it makes sense to write it as common_prefix(?:second_alternative_part_after_prefix)?.

You also have lots of groups in the pattern that seem redundant, same as {1} quantifier that is never necessary in a pattern.

Here is a fixed version of your regex:

/^\d{4}-\d\d-\d\d(?:t[\d:.]*(?:z|[+-]\d\d:?\d\d)?)?$/i

Or, precising it further on to match year-month-days:

/^[12]\d{3}-(?:0?[1-9]|1[0-2])-(?:0[1-9]|[12]\d|3[01])(?:t[\d:.]*(?:z|[+-]\d\d:?\d\d)?)?$/i

If the last \d\d:?\d\d are for minutes and seconds you may replace it with [0-5][0-9]:?[0-5][0-9].

See the regex demo and the regex graph:

enter image description here

enter image description here

Wiktor Stribiżew
  • 607,720
  • 39
  • 448
  • 563