Functional Weave
Code in TypeScript

todo.next-occurrence@1.0.0

README.md

1,707 bytes · view raw

# todo.next-occurrence

When a repeating todo is done, the date it is due next. todo.list's
`toggleTodo` calls it to roll a repeating todo forward.

## The series

Every occurrence is the recurrence's `anchor` (the first due date of the
series) plus a whole number of intervals, computed with
subscriptions.next-billing-date: `daily` steps in days, `weekly` in 7 days,
`monthly` and `yearly` in calendar months with the month-end clamp. So a
monthly todo anchored on 31 January is due 28 February, 31 March, 30 April;
the classic bug is to add a month to the previous due date, which leaves it on
the 28th for ever after February. A yearly todo anchored on 29 February is due
28 February in ordinary years and 29 February again in leap years. An
interval of 2 on `weekly` is every other week, counted from the anchor's week.

`weekdays` is the next Monday to Friday. It has no interval other than 1 and
its anchor does not matter.

## Which occurrence

The answer is the first date of the series strictly after both `due` and
`today`:

- done on the day it is due: the next one (daily: tomorrow);
- done early (a monthly bill due 1 October paid on 28 September): the one
  after the due date, 1 November, not 1 October again;
- done late (a daily todo five days overdue): the next one after today,
  tomorrow. The missed occurrences are skipped rather than left overdue,
  which is what every to-do app does with a habit you catch up on.

`today` is an argument, never the clock: the app passes the user's local date.

## Errors

An unknown frequency, an interval below 1, a weekdays repeat with any other
interval, an impossible date (dates.add-days's message) and an anchor after
the due date are errors.