A maybe-overly-complicated way to solve a seemingly simple problem.
The Problem
Long time no see guys, how have you been doing?
Recently at $DAYJOB we’ve been asked to send monthly timesheets to the HR department by the 28th of each month.
I have a few issues with this:
- The 28th won’t always be a weekday
- I don’t want to turn my work laptop on during the weekends
- Most importantly, I don’t want to have to use what’s little left of my brain to remind of this myself
So, I’d like Google Calendar to remind me to do it on the 28th itself, or the last weekday before it (it could be the 26th or the 27th, depending on whether the 28th is a Saturday or a Sunday).
I tried using the built-in recurring events, but from what I’ve seen they don’t seem to support this kind of recurrence rules.
The Solution
One thing that Google Calendar does support, though, is importing events from .ics files.
So, I created a simple one with the following contents:
BEGIN:VCALENDAR
VERSION:2.0
BEGIN:VEVENT
RRULE:FREQ=MONTHLY;INTERVAL=1;BYMONTHDAY=26,27,28;BYDAY=MO,TU,WE,TH,FR;BYSETPOS=-1
SUMMARY:Send timesheet
DTSTART;TZID=Europe/Rome:20260101T170000
DTEND;TZID=Europe/Rome:20260101T171500
SEQUENCE:0
DESCRIPTION:Export timesheet from XXX and send it to XXX
END:VEVENT
END:VCALENDAR
I saved it on my machine and imported it into Google Calendar using Settings (under the gear icon at the top right) > Import & export (on the left sidebar).
The magic happens in the RRULE property, which defines the recurrence rule for the event. In this case:
FREQ=MONTHLY: the event is set to repeat monthlyINTERVAL=1: the event is set to repeat every month (e.g. you could put2there and it would be every other month)BYMONTHDAY=26,27,28: the event is set to repeat on the 26th, 27th, and 28th of each monthBYDAY=MO,TU,WE,TH,FR: the event is set to repeat on weekdays, which filters out weekendsBYSETPOS=-1: choose the last possible event among the ones defined by the other properties
Here’s a practical example from the current month of February 2026. Applying the BYMONTHDAY and BYDAY properties gives us a set of 2 possible dates:
- Thursday the 26th
- Friday the 27th
Saturday the 28th is filtered out by the BYDAY property. Using the BYSETPOS=-1 property, we choose the last possible event among these two dates, which is Friday the 27th. Success!
Just a couple of notes about DTSTART and DTEND:
- My timezone is
Europe/Romebut you can change it to whatever you want. If you don’t know your timezone identifier, you can find it here in theTZ identifiercolumn - I used the date
20260101but honestly I think you could put whatever date you want in there, as it only affects the start of the recurrence rule (i.e. from when events start appearing in your calendar). The actual dates will always be calculated by theRRULEproperty. - I used the times
17:00and17:15to put the reminder at the end of the day.
Conclusion
This simple solution works quite well for my needs. The only issues are:
- If you ever want to modify the event (e.g. changing the description or the time), you’ll need to delete the recurring event, edit the
.icsfile, and re-import it into Google Calendar - It doesn’t take into account public holidays, or my own personal holidays
but overall I think it’s pretty solid.
Feel free to get in touch if you have any questions or suggestions.
Till next time!
Credits
Huge thanks to this article from Gareth J M Saunders for inspiration!