Two kinds of monthly

By date: the 15th of every month. Same number, different weekday each time. Right for a deadline or a market day fixed to a date.

By weekday: the first Saturday of every month. Different date, same weekday. Right for almost everything a venue does, because people remember “first Saturday” and cannot remember “the 3rd, then the 7th, then the 5th”.

In rule terms these are BYMONTHDAY=15 and BYDAY=1SA. Both are in the expander above.

The 31st problem

Set the rule to FREQ=MONTHLY;BYMONTHDAY=31 and expand a year. You get seven dates, not twelve — the months without a 31st produce nothing at all.

That is correct behaviour and it is what the standard requires: an occurrence that does not exist is skipped, not moved. But it is rarely what the person meant. Somebody who says “the 31st” usually means the last day of the month, and if they configure the 31st they lose five months a year without being told.

The rule they actually wanted is BYMONTHDAY=-1, which counts from the end and gives twelve dates: 31, 28, 31, 30, and so on. Every February handled, leap years included.

Some plugins “helpfully” shift a missing 31st to the 30th or the 1st of the next month. That is worse than skipping, because it is silently inventing a date the rule never described, and it will disagree with every other calendar reading the same rule.

The fifth Friday

“The last Friday of the month” and “the fourth Friday of the month” are the same date most months and different dates four or five times a year. Expand a full year and look at the months with five Fridays: if those dates are not what you expected, you have the wrong one of the two rules.

This is worth doing before printing anything, because it is a small configuration difference and a large embarrassment.

Every other month

Add INTERVAL=2 for bi-monthly. As with fortnightly rules, it is anchored to the start — “every other month from January” and “every other month from February” give you opposite sets. There is no calendar-wide notion of odd and even months; there is only where you started.

The check worth doing

Whatever rule you settle on, expand twelve months and read the dates. It takes fifteen seconds in the tool above, and it catches every one of the traps on this page before they reach a customer.