JonasWanke / rrule

🔁 Recurrence rule parsing & calculation as defined in the iCalendar RFC
https://pub.dev/packages/rrule
Apache License 2.0
52 stars 22 forks source link

SETPOS/bySetPositions is not behaving correctly #68

Closed jonasbadstuebner closed 9 months ago

jonasbadstuebner commented 9 months ago

When testing for #66 to be correct, I ran into an issue, that occurs also without the change I made there, so I open a seperate ticket here.

I tested the following configuration: RRULE:FREQ=WEEKLY;BYDAY=MO,WE;BYSETPOS=2,3

Which corresponds to the following setup:

test('#??: works', () {
  final rrule = RecurrenceRule(
    frequency: Frequency.weekly,
    byWeekDays: [
      ByWeekDayEntry(DateTime.monday),
      ByWeekDayEntry(DateTime.wednesday),
    ],
    bySetPositions: const [2, 3],
  );
  final start = DateTime.utc(2024, 02, 01);

  final instances = rrule.getInstances(start: start).take(5);
  expect(
    instances,
    equals([
      DateTime.utc(2024, 02, 07),
      DateTime.utc(2024, 02, 14),
      DateTime.utc(2024, 02, 21),
      DateTime.utc(2024, 02, 28),
      DateTime.utc(2024, 03, 06),
    ]),
  );
});

I get a test failure:

TestFailure (Expected: [
            DateTime:2024-02-07 00:00:00.000Z,
            DateTime:2024-02-14 00:00:00.000Z,
            DateTime:2024-02-21 00:00:00.000Z,
            DateTime:2024-02-28 00:00:00.000Z,
            DateTime:2024-03-06 00:00:00.000Z
          ]
  Actual: TakeIterable<DateTime>:[
            DateTime:2024-02-07 00:00:00.000Z,
            DateTime:2024-02-14 00:00:00.000Z,
            DateTime:2024-02-12 00:00:00.000Z,
            DateTime:2024-02-21 00:00:00.000Z,
            DateTime:2024-02-19 00:00:00.000Z
          ]

I set a breakpoint here: https://github.com/JonasWanke/rrule/blob/f557fe9e72821c0543b1bf8f56fe5f50d531b07d/lib/src/iteration/set_positions_list.dart#L35

This is on the first hit on the breakpoint: grafik

This is on the second one: grafik

It seems like the setPostion is wrongly calculated. In this setup, setPosition: 3 should never occur, since the events are looked at "on a weekly basis" and a new week starts a new set. Therefore only positions 1 and 2 exist. In this setup, only Wednesdays should be yielded...right?

Environment:

jonasbadstuebner commented 9 months ago

I double checked with the RFC 5545, but couldn't find anything about that this would be an invalid RRULE. rrule.js seems to be very similar to the current implementation in this package. https://github.com/jkbrzt/rrule/blob/master/src/iter/poslist.ts Yet it does show the correct dates.

Code:

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

const ruleOptions = RRule.parseString(
  "RRULE:FREQ=WEEKLY;BYDAY=MO,WE;BYSETPOS=2,3;COUNT=5"
)

ruleOptions.dtstart = datetime(2024, 02, 01);

const rule = new RRule(ruleOptions);

console.log(rule.all())

Output:

[
  2024-02-07T00:00:00.000Z,
  2024-02-14T00:00:00.000Z,
  2024-02-21T00:00:00.000Z,
  2024-02-28T00:00:00.000Z,
  2024-03-06T00:00:00.000Z
]
jonasbadstuebner commented 9 months ago

Found the problem, opened a PR.