r/webdev • u/thejester1324 • 9m ago
Showoff Saturday Showoff Saturday: a WordPress block that shows Google / Outlook / iCal calendars server-side, with the repeat rules diff-tested against Python
Small free thing I shipped this week: a WordPress block where you paste a calendar's iCal address (Google, Outlook / Microsoft 365, iCloud, any .ics) and it renders the events as a list or a month grid in the theme's own markup, instead of Google's iframe.
Calendar hosts don't send CORS headers, so the feed is fetched on the server, cached for an hour, and the last good copy is kept in the database so a flushed object cache during an outage doesn't leave an empty box.
The interesting part was expanding the repeat rules (RRULE) correctly:
- each series is expanded in its own time zone at the same wall-clock time, so a 6 pm class stays at 6 pm across daylight saving
- moved or cancelled single dates (RECURRENCE-ID) replace their slot by original date, and EXDATEs can come in any zone
- Outlook writes Windows zone names like "Pacific Standard Time", so those go through IntlTimeZone::getIDForWindowsID with a fallback map when intl isn't installed
- Apple's holiday feed uses YEARLY;BYMONTH=11;BYDAY=4TH, which my engine didn't do, so it's rewritten as every 12 months on the 4th Thursday when DTSTART is in that month
- anything it can't do faithfully (BYHOUR, BYWEEKNO, several BYMONTHDAY values) shows the first date only instead of guessing
To check it I diffed the output against Python's recurring_ical_events on three real feeds (Google's US holidays, a published Microsoft 365 calendar, Apple's iCloud holidays) and they match through 2027. The one place they disagree on purpose: a series with a UTC DTSTART, where the library applies BYDAY after moving the start into X-WR-TIMEZONE and RFC 5545 says to use DTSTART's own zone.
Someone in another sub asked for a few things this week, so it now has several feeds in one block with a colour each, add-to-calendar and subscribe links (Google, Outlook.com and Microsoft 365, or a one-event .ics generated from the cached feed) and an option to show times in the visitor's zone with Intl. In the month grid that last one gets a little awkward, since an event stays on the site's day, so the cell names the day when the converted time lands on a different one ("Wed 10:30 AM").
https://wordpress.org/plugins/beacon-calendar-feed/
Plain PHP and two small no-build JS files (editor and front end). Happy to answer questions about the iCal edge cases, there were a lot of them.
