Skip to content

madr/date-iso8601

Validates that an ADR’s date field is a valid ISO 8601 calendar date in YYYY-MM-DD format.

The rule reads context.metadata[field], which is YAML frontmatter merged with v2 body-list metadata (frontmatter wins on conflict; explicit null/undefined frontmatter values are skipped). It therefore supports MADR v2 (bold - **Date**: and plain * Date: list items), v3 and v4.

gray-matter parses an unquoted date: 2026-05-01 into a JavaScript Date; the rule normalizes a Date via toISOString().slice(0, 10), keeps a string as-is, and treats anything else (null, boolean, number) as missing. Validation uses a Date.UTC round-trip so leap years and month lengths are handled correctly without external libraries.

  • missingDate — the configured field is absent, or its value is not a string / Date. Message: Metadata does not contain a "<field>" field (checked frontmatter and v2 bold-list), with data.field.
  • invalidDate — the value is present but not a real YYYY-MM-DD date: wrong shape (2026-5-1, 26-05-01, today) or a non-existent calendar date (2026-13-01, 2026-02-31, 2025-02-29). Message: Date "<date>" is not a valid ISO 8601 calendar date (YYYY-MM-DD), with data.date.
---
date: 2026-05-01
---

Leap-year date (quoted so YAML keeps it a string):

---
date: '2024-02-29'
---
FrontmatterDiagnosticReason
(no date)missingDatefield absent
date: 2026-13-01invalidDatemonth 13
date: 2026-02-31invalidDateFebruary has no 31st
date: 2025-02-29invalidDate2025 is not a leap year
date: '2026-5-1'invalidDateunpadded month/day
date: '26-05-01'invalidDate2-digit year
date: 'today'invalidDatenot a date string

This rule is fixable (madr-lint --fix) — but only for v2 body-list dates, where the value has an exact source offset. Frontmatter dates are never rewritten (YAML-aware editing is out of scope), and only unambiguous shapes are normalized. Everything else is left as a report-only diagnostic.

Fixed — normalized to YYYY-MM-DD:

BeforeAfterShape
- Date: 2026/7/3- Date: 2026-07-03year-first numeric (/, . or -, single separator)
- Date: 3 Jul 2026- Date: 2026-07-03day-first English named month
- Date: July 3, 2026- Date: 2026-07-03month-first English named month

Not fixed (reported, never rewritten):

  • Ambiguous day/month order03/07/2026 could be 3 July or 7 March; there is no safe choice, so it is never touched.
  • Two-digit years26/07/03.
  • Impossible calendar dates2026/2/30, 2026/13/01; a fix never turns an invalid date into a different valid one.
  • Non-English or unknown month names3 Mai 2026.
  • Frontmatter-sourced values — a date: in YAML frontmatter (fix an ISO value there by hand).
OptionTypeDefaultDescription
fieldstring'date'Metadata key to read (frontmatter or v2 body-list, with key normalization). Override for projects using e.g. created or updated.
import { defineConfig } from 'madr-lint';
export default defineConfig({
rules: {
'madr/date-iso8601': ['error', { field: 'created' }],
},
});
VersionAppliesNotes
v2yesbody-list - **Date**: 2026-05-01, via the metadata bridge
v3yesfrontmatter date: ...
v4yesfrontmatter date: ...

Set madr/date-iso8601 to off when migrating from a system that uses a different date format. Prefer overriding field to read a custom metadata key.

Like all rules, this rule can be suppressed inline — see Suppressing rules.