/^/
EasyDates3 min read

ISO 8601 Date Regex

Validates a calendar date in ISO 8601 YYYY-MM-DD format, checking that the month is 01-12 and the day is 01-31.

#date#iso8601#validation#dates#calendar

Regex Pattern

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

Pattern Breakdown

Hover over a token to see what it does.

^\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01])$
TokenMeaning
^Anchors the match to the start of the string.
\d{4}Exactly four digits for the year.
-A literal hyphen separating the date components.
(0[1-9]|1[0-2])The month: 01-09 or 10-12.
(0[1-9]|[12]\d|3[01])The day: 01-09, 10-29, or 30-31.
$Anchors the match to the end of the string.

Detailed Explanation

What it does

This pattern matches dates written in the ISO 8601 extended format YYYY-MM-DD, such as 2026-07-10. It requires a four-digit year, a two-digit month between 01 and 12, and a two-digit day between 01 and 31, all separated by hyphens.

Why it works

Each date component is validated with its own alternation. The month group `(0[1-9]|1[0-2])` covers the two valid digit patterns for months 1 through 12, and the day group `(0[1-9]|[12]\d|3[01])` covers days 1-9, 10-29, and 30-31 as three separate ranges. Because regex has no concept of calendar arithmetic, the ranges are purely numeric and don't know which months actually have 30 or 31 days.

Common use cases

  • Validating date input fields in web forms before submission
  • Filtering log lines or filenames that embed an ISO date
  • Pre-checking API payloads that require ISO 8601 date strings
  • Simple format checks before parsing with a full date library

Edge cases

  • 2026-02-30 matches the regex even though February never has 30 days, because the pattern only checks digit ranges
  • 2026-02-29 matches even in non-leap years, since leap-year logic isn't representable with this regex alone
  • Single-digit months or days without a leading zero, like 2026-7-10, correctly fail to match
  • Two-digit years such as 26-07-10 correctly fail because exactly four digits are required

Limitations

  • Does not validate real calendar correctness, such as leap years or month-specific day counts
  • Does not support ISO 8601 date-time strings with time or timezone components
  • Only supports the hyphen-separated extended format, not the compact YYYYMMDD basic format

Interactive Tester

Edit the pattern or text below — matching runs live in your browser.

2026-07-10 2026-02-30

Test Cases

Editable — add your own inputs to see if they pass.

InputExpectedResult
Pass
Pass
Pass
Pass
Pass
Pass
Pass
Pass

Language Variants

Production-ready examples in 12 languages.

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

function isValidIsoDate(value) {
  return isoDatePattern.test(value);
}

console.log(isValidIsoDate("2026-07-10")); // true

Common Mistakes

Assuming a regex match guarantees a real, valid calendar date (e.g. rejecting February 30).

Fix: Use the regex only as a format pre-check, then parse the string with a date library (like `Date` or `chrono`) and verify it round-trips correctly.

Forgetting to require leading zeros, allowing formats like 2026-7-10 to slip through in a hand-rolled variant.

Fix: Keep the two-digit groups `0[1-9]|1[0-2]` and `0[1-9]|[12]\d|3[01]` so single digits without padding are rejected.

Reusing this pattern to validate date-time strings with a time component.

Fix: Extend the pattern with an optional `T` time section, e.g. append `(T([01]\d|2[0-3]):[0-5]\d:[0-5]\d(Z|[+-]\d{2}:\d{2})?)?`.

Performance Notes

  • All quantifiers are bounded (`{4}`, fixed alternation branches), so matching runs in linear time with no backtracking blowup risk.
  • Anchors at both ends make failed matches on wrong-length input fail immediately rather than scanning further.
  • The alternations are mutually exclusive by their leading digit, so the engine rarely needs to backtrack between branches.

Browser Compatibility

EngineSupportedNotes
ChromeYes
FirefoxYes
SafariYes
EdgeYes
Node.jsYes