Skip to main content

patch_rrule

Function patch_rrule 

Source
pub fn patch_rrule(
    recurrence: &str,
    prev_datetime: &str,
    new_datetime: &str,
    tzid: &str,
) -> String
Expand description

Patches a recurrence (RRULE) to reflect moving one occurrence from prev_datetime to new_datetime.

Semantics and timezone rules:

  • prev_datetime and new_datetime are iso date or datetime. IMPORTANT: the datetime should be in local timezone, and therefore without the trailing Z.
  • tzid is the calendar timezone context. All calendar comparisons (weekday, monthday, month) are performed after converting prev_datetime and new_datetime to tzid. (this is mostly useful for the computation of the until, the passed date and datetime are already assumed to be in local time)
  • The produced changes are as if the rule was authored in tzid. For example, moving an event to a different local day (in tzid) will update BYDAY/BYMONTHDAY to match the new local date.
  • If the rule has an UNTIL:
    • UNTIL with trailing Z (e.g., 20250617T220000Z) is interpreted as a UTC datetime and compared in UTC.
    • UNTIL as date-only (e.g., 20250617) is interpreted as local date in tzid at 00:00 and then converted to UTC for comparison.
    • If UNTIL is before new_datetime, it will be updated using the same shape (date-only stays date-only; datetime Z stays datetime Z).

What gets updated:

  • Weekly (FREQ=WEEKLY): updates BYDAY when the local weekday changes. For multi-day lists, replaces only the matching old day with the new one (if not already present).
  • Monthly (FREQ=MONTHLY):
    • If BYMONTHDAY is present, updates the day value(s) that match the old day (supports multiple comma-separated values).
    • If BYDAY contains a position (e.g., 1MO, -1FR), updates both the weekday and the position, handling “last” week (-1) correctly.
  • Yearly (FREQ=YEARLY):
    • If BYMONTHDAY contains a single day value, updates it when the local monthday changes.
    • If BYMONTH is present with a single value and the local month changes, updates BYMONTH accordingly.
    • If BYMONTH is not present and the local month changes, appends BYMONTH with the new month.
    • Note: yearly handling currently targets the single-day birthday-like use case; lists are not modified.

Other behavior:

  • If the input contains multiple lines (e.g., EXDATE + RRULE), only the RRULE line is modified/returned.
  • Parameters unrelated to the above remain untouched (e.g., INTERVAL, COUNT unless UNTIL update requires ignoring COUNT elsewhere).

Arguments:

  • recurrence: full recurrence string or RRULE line.
  • prev_datetime: previous occurrence date or datetime (local, no timezone). format: YYYY-MM-DD or YYYY-MM-DDTHH:MM:SS
  • new_datetime: new occurrence date or datetime (local, no timezone). format: YYYY-MM-DD or YYYY-MM-DDTHH:MM:SS
  • tzid: timezone ID used for calendar logic.

Returns: Modified RRULE string (single line).