calternal_notes_core::nlp::tasks_recurrence_md
Canonical serializer and deserializer for TaskRecurrence.
Issue #430 requires readable repeat: values; RFC 5545 RRULE input and
output use the same structured recurrence so imports remain lossless.
Canonical form (ported from iOS ListItemTaskRecurrenceMarkdown.swift:260-321)
Section titled “Canonical form (ported from iOS ListItemTaskRecurrenceMarkdown.swift:260-321)”| freq | interval | weekdays | month_day | month | output |
|---|---|---|---|---|---|
| Daily | 1 | — | — | — | every day |
| Daily | N | — | — | — | every N days |
| Weekly | 1 | nil/empty | — | — | every week |
| Weekly | N | nil/empty | — | — | every N weeks |
| Weekly | 1 | Mon-Fri | — | — | every weekday |
| Weekly | 1 | Sat+Sun | — | — | every weekend |
| Weekly | 1 | {Mon} | — | — | every Monday |
| Weekly | 1 | {Mon,Wed,Fri} | — | — | every Monday Wednesday Friday |
| Weekly | N | {Mon} | — | — | every N weeks on Monday |
| Monthly | 1 | — | 15 | — | every month on the 15th |
| Monthly | N | — | 15 | — | every N months on the 15th |
| Monthly | 1 | — | nil | — | every month |
| Yearly | 1 | — | 15 | 1 | every Jan 15 |
| Yearly | N | — | 15 | 1 | every N years on Jan 15 |
| Yearly | 1 | — | nil/— | — | every year |
Round-trip invariant
Section titled “Round-trip invariant”recurrence_from_string(&recurrence_to_string(r)) == Some(r.clone())
for every TaskRecurrence that detect_recurrence can produce. The
serializer is designed so every output form is parseable by the T4 parser
(detect_recurrence reused via recurrence_from_string).
Source: crates/calternal-notes-core/src/nlp/tasks_recurrence_md.rs
Functions
Section titled “Functions”recurrence_from_rrule
Section titled “recurrence_from_rrule”pub fn recurrence_from_rrule(value: &str) -> Option<TaskRecurrence>Parse the supported, canonical RRULE subset into the shared Task value. The caller still validates RFC syntax at the CalDAV boundary (#430, #393).
Source: crates/calternal-notes-core/src/nlp/tasks_recurrence_md.rs:253
recurrence_from_string
Section titled “recurrence_from_string”pub fn recurrence_from_string(s: &str) -> Option<TaskRecurrence>Parse a canonical recurrence phrase, including an ISO until date, back to
a TaskRecurrence (#430).
Reuses the T4 detect_recurrence parser over a fresh tokenization of the
string — no duplicate grammar. Returns None when the string is not
recognisable as a recurrence.
Source: crates/calternal-notes-core/src/nlp/tasks_recurrence_md.rs:238
recurrence_from_string_with_when_done
Section titled “recurrence_from_string_with_when_done”pub fn recurrence_from_string_with_when_done(s: &str) -> Option<(TaskRecurrence, bool)>recurrence_from_string, but ALSO accepting a trailing task
when done suffix (#27 T9, spec A §D.6: every day when done, every 3 days when done, …). v1 only parses/stores/round-trips this modifier
VERBATIM (tasks spec §8 D2) — the completion-anchored ROLLING behavior it
requests is v1.1 roll-forward engine work (untouched here; nothing acts
on the modifier yet). Returns the parsed core recurrence plus whether the
suffix was present, so a caller that round-trips the FULL frontmatter
string (extract_task_index’s parse_fm_recurrence) can re-attach it
verbatim via recurrence_to_string_with_when_done — the suffix is
never rejected and never silently stripped.
Source: crates/calternal-notes-core/src/nlp/tasks_recurrence_md.rs:430
recurrence_to_string
Section titled “recurrence_to_string”pub fn recurrence_to_string(r: &TaskRecurrence) -> StringSerialize a TaskRecurrence to its canonical English phrase and optional
ISO end date (#430).
The output is always parseable by recurrence_from_string, giving the
round-trip invariant:
recurrence_from_string(&recurrence_to_string(r)) == Some(r.clone())(within the value shapes that detect_recurrence can produce).
Ported from ListItemTaskRecurrenceMarkdown.recurrencePhrase (Swift
ListItemTaskRecurrenceMarkdown.swift:260-321).
Source: crates/calternal-notes-core/src/nlp/tasks_recurrence_md.rs:138
recurrence_to_string_with_when_done
Section titled “recurrence_to_string_with_when_done”pub fn recurrence_to_string_with_when_done(r: &TaskRecurrence, when_done: bool) -> StringCompanion to [recurrence_from_string_with_when_done]: canonicalize the
core recurrence via recurrence_to_string, then re-append when done
verbatim when when_done is set.
Source: crates/calternal-notes-core/src/nlp/tasks_recurrence_md.rs:438