Regex patterns/Dates & times
ISO date (YYYY-MM-DD)
Month and day ranges enforced by alternation, not by \d{2}.
/^\d{4}-(?:0[1-9]|1[0-2])-(?:0[1-9]|[12]\d|3[01])$/The problem
Check that a string is a calendar date in YYYY-MM-DD form.
How it reads
Follow the line from left to right — every path you can trace is a string this pattern matches.
^\d{4}-(?:0[1-9]|1[0-…In order:^The start of the text (or of a line with the m flag)\d{4}A digit, exactly 4 times, as many as possible-The character "-"(?:0[1-9]|1[0-2])Group (not captured):0[1-9]|1[0-2]Any one of these alternatives:0[1-9]In order:0The character "0"[1-9]Any one of: "1" to "9"1[0-2]In order:1The character "1"[0-2]Any one of: "0" to "2"-The character "-"(?:0[1-9]|[12]\d|3[01…Group (not captured):0[1-9]|[12]\d|3[01]Any one of these alternatives:0[1-9]In order:0The character "0"[1-9]Any one of: "1" to "9"[12]\dIn order:[12]Any one of: "1" or "2"\dA digit3[01]In order:3The character "3"[01]Any one of: "0" or "1"$The end of the text (or of a line with the m flag)
Matches
- 2024-06-01
- 1999-12-31
- 2024-02-30
Does not match
- 2024-13-01
- 24-06-01
- 2024-6-1
- 2024/06/01
Where it bites
- 2024-02-30 passes. A regex counts characters; it cannot know February is short or which years are leap years. Validate the range here and the real date with Date.
- The ranges are spelled out as alternatives because \d{2} would accept month 99.
- It is anchored, so it validates a whole string. Drop the anchors to find dates inside a log line.