Skip to content

Conversation

@KristjanESPERANTO
Copy link
Collaborator

@KristjanESPERANTO KristjanESPERANTO commented Jan 3, 2026

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.000Z in America/Chicago (UTC-6)
  • → Converts to 2025-11-02 18:00:00 (6 hours back)
  • .startOf("day")2025-11-02 00:00:00Wrong day!

Impact: The bug affects:

  • All timezones west of UTC (UTC-1 through UTC-12): Americas, Pacific
  • Timezones east of UTC (UTC+1 through UTC+12): Europe, Asia, Africa - work correctly
  • UTC itself - works correctly

The issue was introduced with commit c2ec6fc (#3976), which fixed the time but broke the date. This PR fixes both.

Result Day Time Notes
Before c2ec6fc 2025-11-03 05:00:00 Monday Wrong time, but correct day
Current (c2ec6fc) 2025-11-02 00:00:00 Sunday ❌ (west of UTC)
✅ (east of UTC)
Wrong day - visible bug!
This fix 2025-11-03 00:00:00 Monday Correct in all timezones

Note: 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:

const utcYear = date.getUTCFullYear();
const utcMonth = date.getUTCMonth();
const utcDate = date.getUTCDate();
return moment.tz([utcYear, utcMonth, utcDate], eventTimezone);

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

@sdetweil
Copy link
Collaborator

sdetweil commented Jan 3, 2026

Is the a matching edge case with one hour close to
DST which should move forward , but doesn’t

@KristjanESPERANTO
Copy link
Collaborator Author

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
@KristjanESPERANTO KristjanESPERANTO changed the title fix(calendar): correct day-of-week for full-day recurring events across DST fix(calendar): correct day-of-week for full-day recurring events across all timezones Jan 3, 2026
@KristjanESPERANTO
Copy link
Collaborator Author

KristjanESPERANTO commented Jan 3, 2026

I just fixed a comment that still referred to DST. No changes in the logic.

@KristjanESPERANTO
Copy link
Collaborator Author

KristjanESPERANTO commented Jan 4, 2026

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.

@sdetweil
Copy link
Collaborator

sdetweil commented Jan 4, 2026

No rush. Not shipping til April 1

@sdetweil
Copy link
Collaborator

sdetweil commented Jan 4, 2026

User reports PR fixed issue

@KristjanESPERANTO
Copy link
Collaborator Author

Great 🙂 Then we can merge it, right?

@sdetweil sdetweil merged commit 40301f2 into MagicMirrorOrg:develop Jan 4, 2026
9 checks passed
@KristjanESPERANTO
Copy link
Collaborator Author

@sdetweil Is the problem serious enough that we should do a fix release? 🤔

@sdetweil
Copy link
Collaborator

sdetweil commented Jan 4, 2026

no, we can teach them how to get the PR

@KristjanESPERANTO
Copy link
Collaborator Author

Okay, I think that's a good call 👍

@KristjanESPERANTO KristjanESPERANTO deleted the calendar branch January 5, 2026 13:53
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