Download Cheat sheet PDF 12 pages · syntax, editors, patterns, Unicode, performance, debugging
Patterns May 2, 2026

Regex to match a date — every common format

Patterns for ISO, US, and European formats — and the reason none of them validate semantic correctness.

The four common formats

1. ISO 8601 (YYYY-MM-DD)

^\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01])$

Matches: 2024-01-15, 1999-12-31

2. US format (MM/DD/YYYY)

^(0[1-9]|1[0-2])/(0[1-9]|[12]\d|3[01])/\d{4}$

Matches: 01/15/2024, 12/31/1999

3. European format (DD/MM/YYYY)

^(0[1-9]|[12]\d|3[01])/(0[1-9]|1[0-2])/\d{4}$

Matches: 15/01/2024, 31/12/1999

4. ISO datetime

^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d+)?(Z|[+-]\d{2}:?\d{2})?$

Matches: 2024-01-15T10:30:00Z, 2024-01-15T10:30:00.123-05:00

The semantic-correctness problem

None of these patterns validate that the date actually exists:

  • February 31st — passes regex, isn't a real date
  • April 31st — passes regex, doesn't exist
  • February 29 in non-leap years — passes regex, isn't valid

Regex is checking structural form, not calendar reality. For real validation, parse with a date library after the regex passes the format check.

Better: regex + date library

Use the regex as a fast format filter, then a library for semantic validation:

JavaScript

function isValidDate(s) {
  if (!/^\d{4}-\d{2}-\d{2}$/.test(s)) return false;
  const d = new Date(s);
  return d.toISOString().slice(0, 10) === s;
}

The round-trip check (parse, then re-format) catches February 31 — it would re-format to March 3, which doesn't match the input.

Python

from datetime import date
import re

def is_valid_date(s):
    if not re.match(r"^\d{4}-\d{2}-\d{2}$", s):
        return False
    try:
        date.fromisoformat(s)
        return True
    except ValueError:
        return False

Restricting the year range

If you want to limit to plausible years (say, 1900-2099):

^(19|20)\d{2}-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01])$

Time formats

24-hour HH:MM:

^([01]\d|2[0-3]):[0-5]\d$

24-hour with seconds:

^([01]\d|2[0-3]):[0-5]\d:[0-5]\d$

12-hour with AM/PM:

^(0?[1-9]|1[0-2]):[0-5]\d\s?(AM|PM|am|pm)$

Extracting dates from prose

To find date-shaped strings in unstructured text:

\b\d{4}-\d{2}-\d{2}\b           ISO dates
\b\d{1,2}/\d{1,2}/\d{2,4}\b      US or EU dates with slashes

Drop the anchors and use the global flag. The \b word boundaries prevent matching dates inside larger numbers like 1-2024-2025.

Date in English text (much harder)

"January 15, 2024" or "the 15th of January" can't be matched cleanly with regex. For natural-language date parsing, use:

  • JavaScript: chrono-node
  • Python: dateparser
  • Java: Natty

These handle "next Tuesday", "two weeks ago", "Q3 2024", and dozens of other formats regex can't.

The takeaway

Use a format-specific regex as the first filter, then parse with a date library for semantic validation. Don't try to make a single regex check both — you'll either miss invalid dates or write something unmaintainable.

For natural-language dates, skip regex entirely and use a date-parsing library.


Related reading


Try this pattern in the explainer

Paste any regex into the live explainer and see what each token means, with example matches in real time.

Open the regex explainer →