Yuvomi
Self-hosted family planner for tasks, calendar, shopping, meals, and budget
Alternative to: cozi, familywall, skylight

v2.61.0
2026-09-01Added
-
Monthly series can repeat on the last day of the month (#960). @PapaZhans asked for it, and until now it could only be approximated: a series begun on 31 January looked like “the last day” and lost that the first time it met a short month. The repetition form has a new choice under “monthly”, and it is the only one of its kind - a start date can express “on the 15th” all by itself, but “on the last day” means a different day every month and has to live in the rule.
Only that one value is accepted, and only under “monthly”. Reading the wider RFC range was tried during review and taken back: accepting values the recurrence engine does not implement opened a failure case for each one.
BYMONTHDAY=31is supposed to be omitted in February rather than moved to the 28th,1,15means two days a month, the same component under a yearly rule means twelve occurrences a year rather than one, and under daily or weekly rules it filters days instead of setting them. A value that is read but computed wrongly moves appointments silently; one that is ignored leaves the series where it was. Rules from other calendars therefore keep behaving exactly as before, and an edit hands them back word for word (#756).The choice survives the places a rule gets rebuilt: cutting a series with “this and all following” keeps it, and a one-time ICS import carries it through. It is not pushed to Outlook, because Microsoft Graph has no equivalent - and the obvious substitute is not one, since a “last weekday of the month” pattern selects the first day matching it rather than the month’s end. Such a series is sent without its recurrence rather than with a different one, and the recurrence is cleared explicitly so an update cannot leave the remote copy on its old schedule.
Fixed
-
A monthly series on the last day of the month no longer skips its first month (#960, follow-up). A series created on 15 January with “on the last day of the month” showed 15 January as its first appointment - a date the rule does not contain - and 31 January was never produced at all. The expansion filter only ever checked the weekday component, so the unmatched start passed as an occurrence, and the next date always jumped to the following month. Both halves are fixed: a date is an occurrence only if it satisfies every part of the rule, and the next occurrence may fall in the same month when the month end is still ahead.
The stored date stays what you entered. Moving it onto the first occurrence when saving was tried and taken back: the reminder, the lead time, the follow-up instance and the list all read that column directly, and none of them learn that the server changed it afterwards. A start date that does not sit on its own rule therefore still goes out verbatim to foreign calendars, where RFC 5545 leaves the result undefined - that belongs in the export path and is tracked separately.
Two smaller consequences of the same distinction: in the calendar a rule with no occurrence at all (a month-end rule whose end date falls before the first month end) is rejected instead of stored as a series nobody will ever see, and the countdown no longer announces a date the calendar does not show. A task is the opposite case and takes no such check: its list reads the due date directly, so a task due on the 15th under a rule that ends on the 20th is due on the 15th and then finished - a valid finite task, not an empty series. The hint under the switch now says what the module it stands in actually does: the calendar computes the series from the start date and shows 31 January, a task stays due on the date you entered and only its next run falls on the month end.
-
“This and all following” no longer empties a series when used on its first appointment. If a series starts on a day its own rule does not contain - a weekly “Mondays only” beginning on a Saturday, which is how some calendars serialise it (#549) - the first appointment shown is not the stored date. Choosing “this and all following” there cut the rule to the day before that first appointment, which leaves a series with nothing in it: the appointment disappeared from the calendar while its record stayed behind with its assignments and exceptions. At the beginning of a series that choice means the whole series, and it is now treated as such - deleting removes it, editing changes it, and neither shortens the rule.
-
A yearly series on 29 February comes back in the next leap year (#978). It used to fall to the 28th after the first non-leap year and stay there - 2024-02-29, then 2025-02-28, and 2028 never returned to the 29th. The cause was the same one behind the monthly clamp fixed in v2.60.0: the intended day was derived from the previous occurrence, so a clamp in a short month wrote itself down permanently. Wherever the series start is known - the calendar, the ICS parser, the series arithmetic - it is now carried along as an anchor. A birthday on 29 February is the case where being one day off is noticed.
Task series are the exception and keep their previous behaviour: a repeating task is a chain of separate rows with no memory of its origin. Nothing existing is migrated.
-
A finite series with weekday restrictions no longer ends early.
FREQ=MONTHLY;BYDAY=MOwith a count of two returned a single appointment: the second count was spent on a Wednesday that was filtered out and never shown. A day outside the weekday pattern is not an occurrence of the series and must not count against the limit - while a date removed by an exception is one and still counts, as the spec requires. The two had been sharing one condition. This is older than the last-day work above and affected any counted series with a weekday restriction.