fix: complete UNTIL/DTSTART value type normalization for rrule-temporal 1.4.2+#433
Conversation
📝 WalkthroughWalkthroughReworked ical.js RRULE/DTSTART/UNTIL handling: detect DATE-only vs DATE-TIME DTSTART, emit Changes
Sequence Diagram(s)mermaid Estimated code review effort🎯 4 (Complex) | ⏱️ ~70 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Fix all issues with AI agents
In `@ical.js`:
- Around line 839-843: The DTSTART line is built using UTC getters which shifts
date-only Date objects created with local components; update the code that
builds dtstartString (currently using
curr.start.getUTCFullYear/getUTCMonth/getUTCDate) to use local getters
(getFullYear, getMonth + 1, getDate) so it matches the getDateKey pattern and
the dateParameter logic (also check any UNTIL validation that assumes local
components); locate the dtstartString construction and the
dateParameter/getDateKey functions to make the change consistently.
…al 1.4.2+ PR jens-maus#432 added initial support for VALUE=DATE preservation, but some edge cases still failed with rrule-temporal 1.4.2+ strict RFC5545 validation. Additional fixes: - Strip time component from UNTIL when DTSTART is DATE-only - Ensure UNTIL has UTC 'Z' suffix for DATE-TIME events - Convert non-UTC UNTIL to UTC when DTSTART has TZID - Embed DTSTART;VALUE=DATE in rruleString for proper validation
e695e38 to
867c441
Compare
There was a problem hiding this comment.
Actionable comments posted: 0
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
ical.js (1)
789-791: Strip TZID fragments when removing inline DTSTART.When rule contains
DTSTART;TZID=..., splitting on;produces a standaloneTZID=...segment that is not filtered out by the current logic. This segment is not valid RRULE syntax and can break rrule-temporal parsing. The filter must also exclude segments starting withTZID=.🛠️ Proposed fix
let rruleOnly = rule.split(';') .filter(segment => !segment.startsWith('DTSTART') && !segment.startsWith('VALUE=')) .join(';'); + let rruleOnly = rule.split(';') + .filter(segment => + !segment.startsWith('DTSTART') + && !segment.startsWith('VALUE=') + && !segment.startsWith('TZID=') + ) + .join(';');
When the internal rule string contains DTSTART;TZID=..., splitting on semicolons produces an orphaned TZID=... segment. This segment is now filtered out along with DTSTART and VALUE= for cleaner RRULE syntax. Note: rrule-temporal tolerates these extra segments, so this is a code quality improvement rather than a bug fix.
Google Calendar sometimes produces invalid RRULE entries where UNTIL is a DATE-only value (YYYYMMDD) even though DTSTART is a DATE-TIME. Examples from real Google Calendars: - DTSTART;TZID=Europe/Oslo:20211216T180000 RRULE:FREQ=WEEKLY;UNTIL=20211216 (missing time!) - DTSTART:20110106T000000Z RRULE:FREQ=YEARLY;UNTIL=20361231 (missing time!) This violates RFC5545 which requires UNTIL to have the same value type as DTSTART. The previous fix in jens-maus#433 only handled the opposite case (DTSTART=DATE with UNTIL having time). Solution: When DTSTART is DATE-TIME but UNTIL is DATE-only, interpret UNTIL as end-of-day (23:59:59) in the event's timezone, then convert to UTC. This correctly handles edge cases like Pacific/Auckland (UTC+13) where a naive T235959Z interpretation would incorrectly include events from the next day. Falls back to T235959Z (UTC) when no timezone info is available. Fixes jens-maus#435 Related: ggaabe/rrule-temporal#104
PR #432 added initial support for VALUE=DATE preservation, but some edge cases still failed with rrule-temporal 1.4.2+ strict RFC5545 validation.
Additional fixes:
Note: Since
rrule-temporalis an active project, we unfortunately have to play catch-up with the changes, but I think that the advantages outweigh this and the migration torrule-temporalwas the right decision.Summary by CodeRabbit
Bug Fixes
Tests
Chores
✏️ Tip: You can customize this high-level summary in your review settings.