Skip to content

fix(calendar): update to node-ical 0.23.1 and fix full-day recurrence lookup#4013

Merged
sdetweil merged 3 commits intoMagicMirrorOrg:developfrom
KristjanESPERANTO:calendar
Jan 12, 2026
Merged

fix(calendar): update to node-ical 0.23.1 and fix full-day recurrence lookup#4013
sdetweil merged 3 commits intoMagicMirrorOrg:developfrom
KristjanESPERANTO:calendar

Conversation

@KristjanESPERANTO
Copy link
Copy Markdown
Collaborator

Adapts calendar module to node-ical changes and fixes a bug with moved full-day recurring events in eastern timezones.

Changes

1. Update node-ical to 0.23.1

2. Remove dead code

  • Removed ineffective UNTIL modification code (rule.options is read-only in rrule-temporal)
  • The code attempted to extend UNTIL for all-day events but had no effect

3. Fix recurrence lookup for full-day events

node-ical changed the behavior of getDateKey() - it now uses local date components for VALUE=DATE events instead of UTC. This broke recurrence override lookups for full-day events in eastern timezones.

Why it broke:

  • before node-ical update: Both node-ical and MagicMirror used UTC → keys matched ✅
  • after node-ical update: node-ical uses local date (RFC 5545 conform), MagicMirror still used UTC → mismatch

Example:

  • Full-day recurring event on October 12 in Europe/Berlin (UTC+2)
  • node-ical 0.23.1 stores override with key: "2024-10-12" (local date)
  • MagicMirror looked for key: "2024-10-11" (from UTC: Oct 11 22:00)
  • Result: Moved event not found, appears on wrong date

Solution: Adapt to node-ical's new behavior by using local date components for full-day events, UTC for timed events.

Note: This is different from previous timezone fixes - those addressed event generation, this fixes the lookup of recurrence overrides.

Background

node-ical 0.23.0 switched from rrule to rrule-temporal, introducing breaking changes. Version 0.23.1 fixed the UNTIL validation issue and formalized the getDateKey() behavior for DATE vs DATE-TIME values, following RFC 5545 specification that DATE values represent local calendar dates without timezone context.

Remove ineffective UNTIL modification and unnecessary tzid clearing.
Simplify timed event conversion. The removed code had no effect
because rule.options is a read-only getter in rrule-temporal.
…rn timezones

When looking up recurrence overrides (moved/modified instances), the dateKey
was always calculated from UTC time. This caused a mismatch for full-day
events in timezones east of UTC (e.g., Europe/Berlin).

Example:
- Full-day event on Oct 12 in Europe/Berlin (UTC+2)
- Old: dateKey = "2024-10-11" (from UTC: Oct 11 22:00)
- New: dateKey = "2024-10-12" (from local date components)

node-ical's getDateKey() uses local date components for VALUE=DATE events,
as per RFC 5545 specification. MagicMirror now matches this behavior.

This fixes moved full-day recurring events not being found in their
recurrence override table, causing them to appear on the wrong date.

Related: node-ical upgrade to 0.23.1
@sdetweil sdetweil merged commit 2d3a557 into MagicMirrorOrg:develop Jan 12, 2026
9 checks passed
@rejas
Copy link
Copy Markdown
Collaborator

rejas commented Jan 12, 2026

Thanks @KristjanESPERANTO this fixed my calendar again

@KristjanESPERANTO
Copy link
Copy Markdown
Collaborator Author

Great 🙂

The switch from rrule to rrule-temporal at node-ical was certainly the right strategic move, but it does come with some migration pains.

@KristjanESPERANTO KristjanESPERANTO deleted the calendar branch January 12, 2026 07:24
@khassel khassel mentioned this pull request Apr 1, 2026
khassel added a commit that referenced this pull request Apr 1, 2026
## Release Notes
Thanks to: @angeldeejay, @in-voker, @JHWelch, @khassel,
@KristjanESPERANTO, @rejas, @sdetweil
> ⚠️ This release needs nodejs version >=22.21.1 <23 || >=24 (no change
to previous release)

[Compare to previous Release
v2.34.0](v2.34.0...v2.25.0)

> ⚠️ We introduced some internal changes with this release, please read
[this forum
post](https://forum.magicmirror.builders/topic/20138/upcoming-release-april-1-2026-breaking-changes-some-operational-changes)
before upgrading!

### [core]
- Prepare Release 2.35.0 (#4071)
- docs: add security policy and vulnerability reporting guidelines
(#4069)
- refactor: simplify internal `require()` calls (#4056)
- allow environment variables in cors urls (#4033)
- fix cors proxy getting binary data (e.g. png, webp) (#4030)
- fix: correct secret redaction and optimize loadConfig (#4031)
- change loading config.js, allow variables in config.js and try to
protect sensitive data (#4029)
- remove kioskmode (#4027)
- Add dark theme logo (#4026)
- move custom.css from css to config (#4020)
- move default modules from /modules/default to /defaultmodules (#4019)
- update node versions in workflows (#4018)
- [core] refactor: extract and centralize HTTP fetcher (#4016)
- fix systeminformation not displaying electron version (#4012)
- Update node-ical and support it's rrule-temporal changes (#4010)
- Change default start scripts from X11 to Wayland (#4011)
- refactor: unify favicon for index.html and Electron (#4006)
- [core] run systeminformation in subprocess so the info is always
displayed (#4002)
- set next release dev number (#4000)

### [dependencies]
- update dependencies (#4068)
- update dependencies incl. electron to v41 (#4058)
- chore: upgrade ESLint to v10 and fix newly surfaced issues (#4057)
- chore: update ESLint and plugins, simplify config, apply new rules
(#4052)
- chore: update dependencies + add exports, files, and sideEffects
fields to package.json (#4040)
- [core] refactor: enable ESLint rule require-await and handle detected
issues (#4038)
- Update node-ical and other deps (#4025)
- chore: update dependencies (#4021)
- chore(eslint): migrate from eslint-plugin-vitest to
@vitest/eslint-plugin and run rules only on test files (#4014)
- Update deps as requested by dependabot (#4008)
- update Collaboration.md and dependencies (#4001)

### [logging]
- refactor: further logger clean-up (#4050)
- Fix Node.js v25 logging prefix and modernize logger (#4049)

### [modules/calendar]
- fix(calendar): make showEnd behavior more consistent across time
formats (#4059)
- test(calendar): fix hardcoded date in event shape test (#4055)
- [calendar] refactor: delegate event expansion to node-ical's
expandRecurringEvent (#4047)
- calendar.js: remove useless hasCalendarURL function (#4028)
- fix(calendar): update to node-ical 0.23.1 and fix full-day recurrence
lookup (#4013)
- fix(calendar): correct day-of-week for full-day recurring events
across all timezones (#4004)

### [modules/newsfeed]
- fix(newsfeed): fix full article view and add framing check (#4039)
- [newsfeed] refactor: migrate to centralized HTTPFetcher (#4023)

### [modules/weather]
- fix(weather): fix openmeteo forecast stuck in the past (#4064)
- fix(weather): fix weathergov forecast day labels off by one (#4065)
- weather: fixes for templates (#4054)
- weather: add possibility to override njk's and css (#4051)
- Use getDateString in openmeteo (#4046)
- [weather] refactor: migrate to server-side providers with centralized
HTTPFetcher (#4032)
- [weather] feat: add Weather API Provider  (#4036)

### [testing]
- chore: remove obsolete Jest config and unit test global setup (#4044)
- replace template_spec test with config_variables test (#4034)
- refactor(clientonly): modernize code structure and add comprehensive
tests (#4022)
- Switch to undici Agent for HTTPS requests (#4015)
- chore: migrate CI workflows to ubuntu-slim for faster startup times
(#4007)

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: Kristjan ESPERANTO <35647502+KristjanESPERANTO@users.noreply.github.com>
Co-authored-by: Bugsounet - Cédric <github@bugsounet.fr>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: sam detweiler <sdetweil@gmail.com>
Co-authored-by: Veeck <github@veeck.de>
Co-authored-by: veeck <gitkraken@veeck.de>
Co-authored-by: Magnus <34011212+MagMar94@users.noreply.github.com>
Co-authored-by: Ikko Eltociear Ashimine <eltociear@gmail.com>
Co-authored-by: DevIncomin <56730075+Developer-Incoming@users.noreply.github.com>
Co-authored-by: Nathan <n8nyoung@gmail.com>
Co-authored-by: mixasgr <mixasgr@users.noreply.github.com>
Co-authored-by: Savvas Adamtziloglou <savvas-gr@greeklug.gr>
Co-authored-by: Konstantinos <geraki@gmail.com>
Co-authored-by: OWL4C <124401812+OWL4C@users.noreply.github.com>
Co-authored-by: BugHaver <43462320+bughaver@users.noreply.github.com>
Co-authored-by: BugHaver <43462320+lsaadeh@users.noreply.github.com>
Co-authored-by: Koen Konst <koenspero@gmail.com>
Co-authored-by: Koen Konst <c.h.konst@avisi.nl>
Co-authored-by: dathbe <github@beffa.us>
Co-authored-by: Marcel <m-idler@users.noreply.github.com>
Co-authored-by: Kevin G. <crazylegstoo@gmail.com>
Co-authored-by: Jboucly <33218155+jboucly@users.noreply.github.com>
Co-authored-by: Jboucly <contact@jboucly.fr>
Co-authored-by: Jarno <54169345+jarnoml@users.noreply.github.com>
Co-authored-by: Jordan Welch <JordanHWelch@gmail.com>
Co-authored-by: Blackspirits <blackspirits@gmail.com>
Co-authored-by: Samed Ozdemir <samed@xsor.io>
Co-authored-by: in-voker <58696565+in-voker@users.noreply.github.com>
Co-authored-by: Andrés Vanegas Jiménez <142350+angeldeejay@users.noreply.github.com>
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.

3 participants