Menu

Search toolsChangelog

to move to openDescribe the problem, not the tool

Monthly dates starting on January 31

A January 31 monthly schedule needs an explicit missing-date rule because February has no 31st. With month-end selected, the first four dates are January 31, February 28, March 31 and April 30 in 2026; with skip selected, February and every other month without a 31st are omitted.

The anchor. Monthly and yearly dates are always derived from this original day, so a short month cannot cause permanent drift.

Days and weeks are fixed lengths. Months and years retain the anchor's calendar day when that day exists.

Includes the first date. The full list downloads even when the table preview is collapsed.

This decides what January 31 monthly means in February, and what February 29 yearly means in a non-leap year.

Last date
2026-12-31
Dates generated
12
First to last (days)
334
Last date falls on
Thursday
Dates moved to month-end
5

The calendar

recurring-dates-2026-01-31.ics · 2.4 KB

One standards-based all-day VEVENT per row, with exclusive next-day DTEND values and stable event identifiers.

Every date in the schedule

12026-01-31Saturday0Anchor date
22026-02-28Saturday28Moved to month end
32026-03-31Tuesday59Exact anchor day
42026-04-30Thursday89Moved to month end
52026-05-31Sunday120Exact anchor day
62026-06-30Tuesday150Moved to month end
72026-07-31Friday181Exact anchor day
82026-08-31Monday212Exact anchor day
92026-09-30Wednesday242Moved to month end
102026-10-31Saturday273Exact anchor day
112026-11-30Monday303Moved to month end
122026-12-31Thursday334Exact anchor day
What to take away
  1. Each candidate is derived from the original day 31, so February 28 does not make March recur on the 28th.

  2. Month-end mode reports every shortened occurrence in the adjustment column.

  3. Skip mode keeps searching candidate months until it has produced the requested number of actual dates.

How it works

How it is done

  1. Parse the first date as a Gregorian calendar anchor, then bound the interval and requested occurrence count before allocating the schedule.
  2. For days and weeks, add a fixed number of UTC calendar days. For months and years, derive every candidate from the original year, month and day rather than from the previous result.
  3. If a candidate month lacks the anchor day, either use its final day or omit that candidate, exactly as selected. Continue until the requested number of actual dates has been produced.
  4. Write the rows as separate RFC 5545 all-day VEVENT components. DTSTART is the date itself, DTEND is the following date because an all-day end is exclusive, and every content line is folded at 75 UTF-8 octets.

What it assumes

  • The calendar is Gregorian and date-only. There is no time of day, time zone, daylight-saving transition or reminder to infer.
  • The first date counts as occurrence one. Twelve dates therefore contain eleven intervals, not twelve.
  • Month-end mode never changes the anchor. January 31 can become February 28 and then return to March 31 because each candidate is derived from the original day 31.
  • Skip mode skips a missing candidate, not an interval. It continues through later candidate months or years until the requested number of real dates exists.
  • Calendar years beyond 9999 cannot be represented by RFC 5545's four-digit DATE value and are not emitted.

Common questions

Why is adding one month repeatedly different from using an anchor day?

If February 28 becomes the input to the next addition, every later month can remain on the 28th. Deriving each date from the original January 31 anchor prevents that permanent drift.

What happens to February 29 on a yearly schedule?

Month-end mode uses February 28 in non-leap years and returns to February 29 in leap years. Skip mode includes only years in which February 29 exists.

Sources

The full method, worked example and every assumption behind this figure are on Recurring Date Schedule Maker.