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

Add documentation how to test if a given time is in the schedule #280

Open pke opened 6 years ago

pke commented 6 years ago

I was really struggling to find out how to test something I'd do in Ruby using schedule.occurring_at? time with RRule. It would be nice if someone could point me to the after, before or between code that returns true if a given time is in the schedule. The answer to this my issue should be added to the docs then ;)

jorroll commented 6 years ago

@pke does !!schedule.between(timeOne, timeOne, true) do what you want?

pke commented 6 years ago

No, this test fails:

import RRule from "rrule"
import * as toDate from "date-fns/parse"

export default function timeInSchedule(schedule:string, time:Date|string|number):boolean {
  const r = RRule.fromString(schedule)
  time = toDate(time)
  return !!r.between(time, time, true)
}

// 2018-09-18 is a TUESDAY and should not be in the schedule
test.false(timeInSchedule("RRULE:FREQ=WEEKLY;BYDAY=MO", Date.UTC(2018,8,18)))

*edit: That is because between always returns an array. If its not in the schedule then the array is empty. So !![] would always evaluate to true. The correct way to do that is between(time, time, true).length > 0 it seems. Does this make sense?

But now this test fails: test.true(timeInSchedule_1.default("RRULE:FREQ=WEEKLY;BYDAY=MO", Date.UTC(2018, 8, 17)));

jorroll commented 6 years ago

Ah right. Forgot about the array return.

Well, its possible that when you performed the test, new Date().getUTCDate() === 18 (which is what it currently equals). Since your rrule string doesn't have a DTSTART time, I'm guessing it's defaulting to new Date(). So, if the rrule string starts on the 18th, and the time you're checking is for the 17th, then it would make sense that it would fail.

You could rule this possibility out by adding a DTSTART time to your ical string. I think rrule now parses standard ical strings (thanks to @davidgoli), so you could do something like:

test.true(timeInSchedule_1.default("DTSTART:20180817T000000Z\nRRULE:FREQ=WEEKLY;BYDAY=MO", Date.UTC(2018, 8, 17)));