Skip to content

Comments

fix: exclude timed EXDATE instances crossing UTC midnight due to DST#464

Merged
jens-maus merged 1 commit intojens-maus:masterfrom
KristjanESPERANTO:exdate
Feb 22, 2026
Merged

fix: exclude timed EXDATE instances crossing UTC midnight due to DST#464
jens-maus merged 1 commit intojens-maus:masterfrom
KristjanESPERANTO:exdate

Conversation

@KristjanESPERANTO
Copy link
Contributor

@KristjanESPERANTO KristjanESPERANTO commented Feb 22, 2026

While implementing expandRecurringEvent in MagicMirror I noticed a subtle bug: recurring timed events with an EXDATE weren't always excluded correctly.

The culprit is a DST edge case — when an event's local time crosses UTC midnight (e.g. 16:00 PST = 00:00 UTC the next day), the date-only key from generateDateKey() ("2023-11-09") matches neither key stored by the parser ("2023-11-08" local date, or "2023-11-09T00:00:00.000Z" full ISO string).

The fix adds a fallback to the full ISO string lookup, consistent with the dual-key storage already in the parser.

Includes a regression test with a weekly 16:00 America/Los_Angeles event and an EXDATE on the first occurrence after the PDT→PST switch.

Summary by CodeRabbit

  • Bug Fixes

    • Improved handling of excluded recurring event instances (EXDATE) by expanding lookup to cover additional key formats, ensuring events are properly excluded even during daylight saving time transitions.
  • Tests

    • Added test cases validating EXDATE exclusion during UTC midnight crossings caused by DST changes.

When a recurring timed event has an EXDATE and the event time crosses
UTC midnight due to a DST offset (e.g. 16:00 PST = 00:00Z the next day),
the instance was not excluded as expected.

generateDateKey() returns the UTC date portion (e.g. "2023-11-09"), but
the EXDATE parser stores two keys for the occurrence:
- "2023-11-08" — the local calendar date (via getDateKey/Temporal)
- "2023-11-09T00:00:00.000Z" — the full ISO string

Neither matched "2023-11-09", so the EXDATE check silently failed.

Fix: fall back to the full ISO string lookup when the date-only key
misses, matching the full-ISO key already stored by the dual-key parser.

Add regression test covering a weekly 16:00 America/Los_Angeles event
with an EXDATE on the first occurrence after the PDT→PST switch.
@coderabbitai
Copy link

coderabbitai bot commented Feb 22, 2026

No actionable comments were generated in the recent review. 🎉


📝 Walkthrough

Walkthrough

The pull request extends EXDATE exclusion logic to check both a generated dateKey and ISO string representation (date.toISOString()) for non-full-day recurring events, and adds test coverage for EXDATE handling across DST boundaries.

Changes

Cohort / File(s) Summary
EXDATE Lookup Enhancement
node-ical.js
Added dual-key EXDATE lookup for non-full-day recurring events: now checks both event.exdate[dateKey] and event.exdate[date.toISOString()] to broaden exclusion coverage.
EXDATE DST Test Cases
test/expand-recurring-event.test.js
Added two test cases validating EXDATE exclusion for weekly recurring events with times when EXDATE dates cross UTC midnight due to DST transitions (PST/PDT), ensuring correct instance exclusion while preserving adjacent occurrences.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Possibly related PRs

Poem

🐰 A rabbit hopped through dates so fine,
But timezones made the schedule malign,
ISO strings we now consult with glee,
Dual keys for exceptions—now decree!
DST no longer dims our sight,
Each excluded event, perfectly right! 🕐

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately and concisely describes the main bug fix: adding support for EXDATE exclusion of timed events that cross UTC midnight due to DST transitions. It directly reflects the core change in node-ical.js and the regression test added.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@KristjanESPERANTO
Copy link
Contributor Author

The "1 configuration not found" CodeQL warning is a pre-existing issue unrelated to this PR — commit 54bef15 renamed the language from javascript to javascript-typescript, leaving stale baseline results on master. This will resolve itself on the next push to master.

Coderabbit seems satisfied. In my view, this can be merged 🙂

@jens-maus jens-maus merged commit f18b061 into jens-maus:master Feb 22, 2026
16 of 17 checks passed
@KristjanESPERANTO KristjanESPERANTO deleted the exdate branch February 22, 2026 11:04
@KristjanESPERANTO
Copy link
Contributor Author

@jens-maus Thanks for the quick merges! A new release would be nice since this blocks my efforts implementing expandRecurringEvent in MagicMirror 🙂

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.

2 participants