diff --git a/CHANGELOG.txt b/CHANGELOG.txt index d505096..fc8d8e0 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -6,6 +6,7 @@ * Added type annotations for public API and `py.typed` marker (PEP 561) * Added `message` to `JsonSchemaValuesException` joining messages of all collected errors * Fixed the `date-time` format accepting months, days and hours out of range (such as `2020-19-39T29:00:00Z`) and rejecting a leap second (`23:59:60Z`) +* Fixed the `date` and `date-time` formats accepting days that do not exist in their month, such as `2021-02-29` and `2021-04-31` * Fixed the `time` format accepting hours, minutes, seconds and offsets out of range (such as `29:99:99`) === 2.22.2 (2026-08-15) diff --git a/fastjsonschema/draft04.py b/fastjsonschema/draft04.py index d86c592..0343e12 100644 --- a/fastjsonschema/draft04.py +++ b/fastjsonschema/draft04.py @@ -18,6 +18,13 @@ DOLLAR_FINDER = re.compile(r"(?\d{4})-(?P(0[1-9]|1[0-2]))-(?P(0[1-9]|[12]\d|3[01]))\Z', + 'date': r'^(?:' + DATE_REGEX + r')\Z', 'iri': r'^\w+:(\/?\/?)[^\s]+\Z', 'iri-reference': r'^(\w+:(\/?\/?))?[^#\\\s]*(#[^\\\s]*)?\Z', 'idn-email': r'^[^@]+@[^@]+\.[^@]+\Z', diff --git a/tests/test_format.py b/tests/test_format.py index 637d500..10b6257 100644 --- a/tests/test_format.py +++ b/tests/test_format.py @@ -28,6 +28,11 @@ ('2020-01-01T01:01:61Z', exc), ('2020-01-01T01:01:01+24:00', exc), ('2020-01-01T01:01:01+01:60', exc), + ('2020-02-30T01:01:01Z', exc), + ('2021-02-29T01:01:01Z', exc), + ('2021-04-31T01:01:01Z', exc), + ('2020-02-29T01:01:01Z', '2020-02-29T01:01:01Z'), + ('2021-04-30T01:01:01Z', '2021-04-30T01:01:01Z'), ]) def test_datetime(asserter, value, expected): asserter({'type': 'string', 'format': 'date-time'}, value, expected) @@ -81,6 +86,20 @@ def test_time(asserter, value, expected): ('2018-2-5', exc), ('2018-02-05', '2018-02-05'), ('2018-10-31', '2018-10-31'), + ('2018-02-29', exc), + ('2018-02-30', exc), + ('2018-04-31', exc), + ('2018-06-31', exc), + ('2018-09-31', exc), + ('2018-11-31', exc), + ('1900-02-29', exc), + ('2100-02-29', exc), + ('2020-02-29', '2020-02-29'), + ('2000-02-29', '2000-02-29'), + ('2400-02-29', '2400-02-29'), + ('2018-02-28', '2018-02-28'), + ('2018-04-30', '2018-04-30'), + ('2018-12-31', '2018-12-31'), ]) def test_date(asserter, value, expected): asserter({