fix(calendar): correct day-of-week for full-day recurring events across all timezones#4004
Conversation
|
Is the a matching edge case with one hour close to |
|
I initially thought this was DST-related too, but after testing I just updated the PR text - it's not about DST. The bug affects all full-day events in western timezones (UTC-1 to UTC-12), regardless of DST: // Western timezones: Always wrong
moment.tz(new Date("2025-11-03T00:00:00Z"), "America/Chicago")
// → 2025-11-02 18:00 → .startOf("day") → 2025-11-02 ❌
// Eastern timezones: Always correct
moment.tz(new Date("2025-11-03T00:00:00Z"), "Asia/Tokyo")
// → 2025-11-03 09:00 → .startOf("day") → 2025-11-03 ✅No matching edge case exists - the bug is asymmetric. UTC midnight converts to the previous day in western timezones, but same day in eastern timezones. That's why eastern timezones work correctly by design. |
…ss DST Full-day recurring events were showing on wrong day after DST transitions. rrule.js returns UTC dates that shift calendar days when offset changes. Fix: Extract UTC date components and interpret as local calendar dates, preserving the intended day regardless of DST offset changes. Added test for weekly Monday event crossing DST boundary. Fixes: MagicMirrorOrg#4003 Regression from: c2ec6fc
e37df6d to
4dda8c3
Compare
|
I just fixed a comment that still referred to DST. No changes in the logic. |
|
I'm too tired to continue researching right now, but after further investigation, it seems to me that the old logic before c2ec6fc is not as wrong as I described it above 🤯. But that doesn't change the fact that we need a fix (this PR) now. I hope that we switch to Temporal at some point, then all the time zone stuff will be a little less confusing. |
|
No rush. Not shipping til April 1 |
|
User reports PR fixed issue |
|
Great 🙂 Then we can merge it, right? |
|
@sdetweil Is the problem serious enough that we should do a fix release? 🤔 |
|
no, we can teach them how to get the PR |
|
Okay, I think that's a good call 👍 |
## 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>
Fixes full-day recurring events showing on wrong day in timezones west of UTC (reported in #4003).
Root cause:
moment.tz(date, eventTimezone).startOf("day")interprets UTC midnight as local time:2025-11-03T00:00:00.000Zin America/Chicago (UTC-6)2025-11-02 18:00:00(6 hours back).startOf("day")→2025-11-02 00:00:00❌ Wrong day!Impact: The bug affects:
The issue was introduced with commit c2ec6fc (#3976), which fixed the time but broke the date. This PR fixes both.
2025-11-03 05:00:00 Monday2025-11-02 00:00:00 Sunday✅ (east of UTC)
2025-11-03 00:00:00 MondayNote: While the old logic had incorrect timing, it produced the correct calendar day due to how it handled UTC offsets. The current logic fixed the timing issue but introduced the more visible calendar day bug.
Solution
Extract UTC date components and interpret as local calendar dates:
Testing
To prevent this from happening again in future refactorings, I wrote a test for it.
npm test -- tests/unit/modules/default/calendar/calendar_fetcher_utils_spec.js