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.33k stars 511 forks source link

Broken toString() conversion when using string in byweekday parameter #493

Open AntonyChiossi opened 2 years ago

AntonyChiossi commented 2 years ago

Reporting an issue

Thank you for taking an interest in rrule! Please include the following in your report:

const { RRule, RRuleSet, rrulestr } = require('rrule');

// Create a rule:
const rule = new RRule({
  freq: RRule.WEEKLY,
  interval: 5,
  byweekday: ['SA'],
  dtstart: new Date(Date.UTC(2012, 1, 1, 10, 30)),
  until: new Date(Date.UTC(2012, 12, 31))
})

console.log(rule.toString());

"DTSTART:20120201T103000Z\nRRULE:FREQ=WEEKLY;INTERVAL=5;BYDAY=undefined;UNTIL=20130131T000000Z"

KrisLau commented 2 years ago

Try using rrulestr https://github.com/jakubroztocil/rrule/issues/335#issuecomment-491618091 instead

Meligy commented 2 years ago

I have the same problem, and the comment before does not help. RRuleSet takes an RRule still, and the toString() seems to still have the same issue as RRule, and using .exrule() instead of .rrule() didn't seem to make a difference.

ekilah commented 2 years ago

seems like the tests in my older PR #371 (that allowed using e.g. 'MO') should cover the toString output, and there is a bug to fix here

equal-matt commented 1 year ago

I'm seeing this too. I've tried both v2.7.0 and v2.7.1 now. For me, the workaround was to always normalise the weekday representations as the Weekday type. Here's my file in case anyone else needs them:

import { ByWeekday, RRule, Weekday, WeekdayStr } from "rrule";
import isDefined from "../isDefined"; // this is a type guard

function numberToWeekdayString(input: number): Weekday {
  switch (input) {
    case 0:
      return RRule.MO;
    case 1:
      return RRule.TU;
    case 2:
      return RRule.WE;
    case 3:
      return RRule.TH;
    case 4:
      return RRule.FR;
    case 5:
      return RRule.SA;
    case 6:
      return RRule.SU;
    default:
      throw `Unknown weekday number ${input}`;
  }
}

const WEEKDAY_STRINGS = ["MO", "TU", "WE", "TH", "FR", "SA", "SU"];
function stringToWeekday(input: typeof WEEKDAY_STRINGS[number]): Weekday {
  switch (input) {
    case "MO":
      return RRule.MO;
    case "TU":
      return RRule.TU;
    case "WE":
      return RRule.WE;
    case "TH":
      return RRule.TH;
    case "FR":
      return RRule.FR;
    case "SA":
      return RRule.SA;
    case "SU":
      return RRule.SU;
    default:
      throw `Unknown weekday number ${input}`;
  }
}

type NormaliseByWeekdayInput =
  | ByWeekday
  | string
  | {
      weekday: number;
    }
  | null
  | undefined;

export function normaliseByWeekdayItem(
  input: NormaliseByWeekdayInput
): Weekday | undefined {
  if (!input) return undefined;
  if (typeof input === "object") {
    return numberToWeekdayString(input.weekday);
  }
  if (typeof input === "number") {
    return numberToWeekdayString(input);
  }
  if (typeof input === "string") {
    return stringToWeekday(input);
  }
  return input;
}

export function normaliseByWeekday(
  input: NormaliseByWeekdayInput | NormaliseByWeekdayInput[]
) {
  if (Array.isArray(input))
    return input.map(normaliseByWeekdayItem).filter(isDefined);
  return normaliseByWeekdayItem(input);
}
frozencap commented 1 year ago

Getting this bug too, rule.toString doesn't parse byweekday properly when you pass it WeekdayStr[], e.g. ["MO", "FR"].

Should be fixed either in the code or in the docs but in the meantime, simple fix

  byweekday: selectedWeekdayStrs.map(b => RRule[b])