jkbrzt / rrule

JavaScript library for working with recurrence rules for calendar dates as defined in the iCalendar RFC and more.
https://jkbrzt.github.io/rrule
Other
3.27k stars 507 forks source link

Removing an exdate #541

Open jk3001 opened 2 years ago

jk3001 commented 2 years ago

Hi, first of all thanks for the nice library!

Is there a way to remove an exdate from an rruleSet? I see it is possible to add one using rruleSet.exdate(), but I how do you get it out again?

I tried filtering the exdate array and writing to _exdate directly, but it is read only.

So how can I achieve this?

topherauyeung commented 1 year ago

i ran into this issue and wrote the following workaround using Luxon. since the library doesn't have a native removal API for exdates, you basically just have to reconstruct the entire RRuleSet from scratch and just exclude the exdate in the new set:

export function removeExceptionDateFromRecurrenceRules(
  recurrenceRules: string[],
  dateTime: DateTime
) {
  const oldRuleSet = getRuleSetFromRecurrenceRules(recurrenceRules);
  const oldExdates = oldRuleSet.exdates();
  if (oldExdates.length === 0) {
    return recurrenceRules;
  }

  const newExdates = oldExdates.filter(d => {
    // for our use case, we only need to match on the hour - you can get more granular if need be
    return !dateTime.hasSame(DateTime.fromJSDate(d), "hour");
  });
  if (newExdates.length === oldExdates.length) {
    throw Error(
      "Tried to remove an exdate that does not exist on the specified recurrence rules"
    );
  }

  const rules = oldRuleSet.rrules();
  const newRuleSet = new RRuleSet();
  rules.forEach(r => newRuleSet.rrule(r));
  newExdates.forEach(d => newRuleSet.exdate(d));
  return newRuleSet.valueOf();
}