Add ISO8601 parser implementation
ISO8601 / EDTF Parser Implementation
Introduces a parser and validator for ISO 8601 and EDTF date/time formats.
-
Core ISO 8601 parsers:
-
CalendarDate
(YYYY, YYYY-MM-DD, YYYYMMDD) -
OrdinalDate
(YYYY-DDD, YYYYDDD) -
WeekDate
(YYYY-Www[-D], YYYYWww[D]) -
Time
+ time zones (extended, basic, optionalT
prefix) -
DateTime
(full date + time, day precision required) -
Duration
(PnYnMnDTnHnMnS, PnW) -
Interval
(start/end, start/duration, duration/end, incl. open/unknown bounds) -
RepeatingInterval
(R/<interval>, Rn/<interval>)
-
-
EDTF extensions (optional):
-
UncertainDate
(? ~ %
qualifiers) -
UnspecificDate
(X
digits) -
SubYearDate
(codes 21–41: seasons, quarters, quadrimesters, semesters) -
DateSet
([ ... ]
= one-of,{ ... }
= inclusive, supports ranges..
) -
LegacyDuration
(P<date>T<time>
)
-
How to:
>>> # Basic usage
>>> parser = ISO8601Parser()
>>> valid, obj = parser.validate("2023-12-25T14:30:45Z")
>>> print(valid) # True
>>> print(type(obj).__name__) # "CalendarDate"
>>> print(obj.format) # "YYYY-MM-DD"
>>> if valid:
... result = parser.parse("2023-12-25T14:30:45Z")
... print(result["type"]) # "DateTime"
... print(result["parsed"]) # {'year': 2023, 'month': 12, ...}
>>> # With EDTF extensions
>>> edtf_parser = ISO8601Parser(include_edtf=True)
>>> edtf_parser.validate("2023?") # True (uncertain)
>>> edtf_parser.validate("198X") # True (unspecified)
>>> edtf_parser.validate("[2023,2024]") # True (date set)
>>> # With legacy support
>>> legacy_parser = ISO8601Parser(include_legacy=True)
>>> legacy_parser.validate("P0023-01-15T14:30:45") # True (legacy duration)
>>> # Custom parser with only specific formats
>>> custom_parser = ISO8601Parser(include_classes=['CalendarDate', 'Time'])
>>> custom_parser.validate("2023-12-25") # True
>>> custom_parser.validate("P1Y") # False (Duration excluded)
>>> # Parser excluding certain formats
>>> filtered_parser = ISO8601Parser(exclude_classes=['Duration', 'LegacyDuration'])
>>> filtered_parser.validate("2023-12-25") # True
>>> filtered_parser.validate("P1Y") # False (Duration excluded)