Skip to content

Add ABNF-driven leap year boundary tests for format: date (RFC 3339 S5.6 + Appendix C)#884

Open
vtushar06 wants to merge 5 commits intojson-schema-org:mainfrom
vtushar06:add-date-leap-year-boundary-tests
Open

Add ABNF-driven leap year boundary tests for format: date (RFC 3339 S5.6 + Appendix C)#884
vtushar06 wants to merge 5 commits intojson-schema-org:mainfrom
vtushar06:add-date-leap-year-boundary-tests

Conversation

@vtushar06
Copy link
Copy Markdown

@vtushar06 vtushar06 commented Mar 24, 2026

Following the methodology established for ipv4, I read RFC 3339 S5.6 and Appendix C and found gaps in the current date.json coverage.

The existing suite tests basic leap years (2020 as leap, 2021 as non-leap) but does not cover the full century leap year matrix or year zero which RFC 3339 S1 explicitly permits.

Changes

  • Added 8 test cases across 4 draft directories (draft2020-12, draft2019-09, draft7, v1)
  • Century years: 0100-02-29 invalid, 0400-02-29 valid, 2100-02-29 invalid
  • Year zero: 0000-02-29 valid (0 mod 400 == 0)
  • ABNF boundary: leading and trailing whitespace invalid per date grammar production
  • ABNF boundary: month 00 and day 00 invalid per date-month and date-mday ranges

Ecosystem Impact

  1. ajv-formats full mode: PASSES all 8 cases
    isLeapYear() at formats.ts matches RFC 3339 Appendix C formula exactly

  2. python-jsonschema v4.x: FAILS 2 cases
    "0000-02-29" rejected via datetime.MINYEAR=1 in Python stdlib - year zero raises ValueError before leap year logic runs.
    Note: "0000-01-01" already exists in test suite as valid:true but python-jsonschema currently fails it.

  3. sourcemeta/blaze: FAILS all 8 cases
    Format validation is annotation-only by design.

RFC References

Related: #965

@vtushar06 vtushar06 requested a review from a team as a code owner March 24, 2026 13:06
Copilot AI review requested due to automatic review settings March 24, 2026 13:06
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds missing RFC 3339–aligned edge cases to the JSON Schema Test Suite’s format: date coverage, focusing on leap-year century rules, year zero, and ABNF boundary constraints.

Changes:

  • Adds leap-year boundary tests for century years (0100/0400/2100) and year zero (0000-02-29).
  • Adds ABNF grammar boundary tests rejecting leading/trailing whitespace.
  • Adds range boundary tests rejecting month 00 and day 00.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.

File Description
tests/v1/format/date.json Adds 8 new format: date test cases for leap-year and ABNF boundaries in v1.
tests/draft7/optional/format/date.json Mirrors the same 8 new format: date cases for draft7 optional format tests.
tests/draft2020-12/optional/format/date.json Mirrors the same 8 new format: date cases for draft2020-12 optional format tests.
tests/draft2019-09/optional/format/date.json Mirrors the same 8 new format: date cases for draft2019-09 optional format tests.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@vtushar06
Copy link
Copy Markdown
Author

Hi @jdesrosiers @jviotti ,

while studying the RFC 3339 grammar I noticed the current suite covers basic leap years (2020, 2021) but not the full century matrix from Appendix C. Since python-jsonschema currently fails the year-zero case (0000-02-29) due to datetime.MINYEAR=1, these feel worth having.

@karenetheridge
Copy link
Copy Markdown
Member

Note: "0000-01-01" already exists in test suite as valid:true but python-jsonschema currently fails it.

I don't see that in the existing tests.

There is no year 0000.

@vtushar06
Copy link
Copy Markdown
Author

You are absolutely right, and I apologize-that claim was wrong. I misread my own notes. "0000-01-01" does NOT currently exist in the test suite.

Regarding year 0000 itself: RFC 3339 §1 explicitly states:

"All dates and times are assumed to be in the 'current era', somewhere between 0000AD and 9999AD."
https://www.rfc-editor.org/rfc/rfc3339#section-1

I understand there's no year 0000 in historical calendars, but RFC 3339 syntactically permits it. When I tested ajv-formats manually, it accepts "0000-02-29" by applying the Appendix C formula (0 % 400 == 0 → leap year).

should I:

  1. Remove only the year 0000 test ("0000-02-29")
  2. Keep the other 7 tests which are uncontroversial: century years 0100/0400/2100, whitespace, and month/day 00

Would that address your concerns? The century year tests (0100, 0400, 2100) are the main gap I was trying to fill-they test the full RFC 3339 Appendix C leap year matrix without the year-zero controversy.

@karenetheridge
Copy link
Copy Markdown
Member

I think the other tests are fine -- but is the specification clear about whether leading zeroes are accepted (some systems might interpret them as octal numbers)?

@vtushar06
Copy link
Copy Markdown
Author

Hi @karenetheridge,

RFC 3339 §5.6 defines dates using ABNF grammar where date-fullyear = 4DIGIT. In ABNF, DIGIT means the ASCII
characters 0–9 (decimal only). There is no concept of octal in ABNF - leading zeros here just mean "pad to the required
width", not a different number base.

So 0400 is simply the year 400 written with the required four digits. Same as how 02 for February is not octal
it is just the required two-digit form.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants