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.
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.
| Token | Meaning |
|---|---|
| ^ | 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.
Test Cases
Editable — add your own inputs to see if they pass.
| Input | Expected | Result | |
|---|---|---|---|
| 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")); // trueCommon 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
| Engine | Supported | Notes |
|---|---|---|
| Chrome | Yes | — |
| Firefox | Yes | — |
| Safari | Yes | — |
| Edge | Yes | — |
| Node.js | Yes | — |