Skip to content

RFC 5545 compliance: parsing, formatting, and tests#4

Open
craigk wants to merge 3 commits intokubens:mainfrom
craigk:main
Open

RFC 5545 compliance: parsing, formatting, and tests#4
craigk wants to merge 3 commits intokubens:mainfrom
craigk:main

Conversation

@craigk
Copy link

@craigk craigk commented Feb 18, 2026

great project. Thank you for sharing.

I make some enhancements to align tighter to the RFC implementation because I needed to interoperate with another rrule package https://github.com/jkbrzt/rrule

All of my changes include test coverage
Let me know if you requires upstream changes to merge it into the mainline.


Changelog
Parsing (RFC 5545–aligned)

  • Rule part names and values are case-insensitive (e.g. FREQ, BYDAY).
  • Parts can appear in any order; exactly one FREQ is required (exact key).
  • Content lines are unfolded on input (CRLF/LF + leading space/HTAB).
  • WKST is accepted (not stored); BYSECOND allows 0–60 (leap second); UNTIL hour 24 is normalized to next day 00:00.

Formatting

  • Optional line folding at 75 octets (foldLongLines) and optional WKST=MO output (emitWKST) so generated strings comply with RFC 5545 line length and WKST.

Safety

  • Replaced force unwraps in buffer resize and date handling with guards/nil‑coalescing to avoid crashes on malformed or edge-case input.

Tests

  • Parse tests: case-insensitivity, arbitrary part order, key rules (FREQUENCY vs FREQ, SECONDLY rejected, duplicate keys), unfolding, WKST, BYSECOND=60, and parse failure as NSError with expected domain/code.
  • Format tests: folding, emitWKST, and large-rule output checked semantically.
  • Round-trip tests: parse→format→parse and format→parse→format, including UNTIL (date, UTC, TZID) and BY*/BYDAY/TZID.

Docs

  • Docs and README updated with RFC 5545 parsing/formatting rules, options, and limitations.

…lding

- Parse rule part names and enum values case-insensitively (FREQ, BYDAY, etc.).
- Accept rule parts in any order; require exactly one FREQ (exact key match).
- Unfold content lines on parse (CRLF/LF + SPACE/HTAB removed).
- Add optional foldLongLines and emitWKST to format style; fold at 75 octets when enabled.
- Parse and accept WKST (not persisted); optional WKST=MO on format.
- BYSECOND 0–60 (leap second), UNTIL hour 24 normalized to next day 00:00.
- Replace force unwraps in buffer resize and date components with guards/nil-coalescing.
Parse tests:
- Case-insensitivity (freq=daily, mixed-case key/value).
- Rule part order (COUNT=5;FREQ=DAILY parses).
- FREQUENCY vs FREQ (exact key), SECONDLY throws, duplicate keys throw.
- WKST accepted, content-line unfolding (CRLF and LF), BYSECOND=60.
- Error contract: parse failure throws NSError with NSCocoaErrorDomain and formatting code.
- Parse via RecurrenceRule(strategy:) (ParseStrategy API).

Format tests:
- foldLongLines (no line >75 octets), emitWKST and default no WKST.
- Large-rule format with semantic substring checks (not just length).
- Format via rule.formatted(style) (FormatStyle API).
- Replace force unwraps with #require in UNTIL format tests.

Round-trip tests:
- Parse → format → parse (simple, UNTIL date, UNTIL UTC, UNTIL TZID, multiple BY*).
- Format → parse → format (simple rule, rule with UNTIL and BYDAY).
- TZID round-trip with same calendar (America/New_York).
DocC:
- Update ParsingRFC5545 and FormattingRFC5545 with new options and rules.
- Link from main Documentation to parsing/formatting topics.

README:
- Add "Key RFC 5545 parsing rules" (any order, case-insensitivity, folding, WKST, no SECONDLY).
- Add "Add-ons" section (placeholder or link to interop).
- Add "Enforced Rules" and expand Limitations (errata).
- Update Testing list (round-trip, large-rule semantic checks).
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.

1 participant