Closed PJ-DSI-DevOps closed 7 years ago
You're close, but you're a little off in understanding how the base date is used. The useage for the parse method is:
(STRING, MODIFIERS, BASE, START, END)
so you've supplied STRING and BASE.
The base date is used to define the 0th occurence. Events after that are numbered 1, 2, etc. and events before that are numbered -1, -2, etc.
For a monthly event, the base date is used only to define which month the 0th event will occur in. For a weekly event, the base date specifies which week, for a daily event, which day, etc. So for your monthly event, your base date (Aug 28, 2017) is used to specify the month, which means that the 0th event will be in Aug 2017. The day-of-month (28) portion of the base date is ignored entirely.
So when you create the recurrence, it is pointing at the 0th event which is (based on your base date) the 2nd Tuesday in August or Aug 8, 2017.
The prev method goes back one event, which means the 2nd Tuesday in July, or July 11. So everything is working as expected.
If you need to find the first event (going back from a specific date, you will need to test the date. Because it's difficult to say that the base date will be before or after the 0th event, you can't assume 'prev' will give it to you. With modifiers, you can't even assume that it will be the first one before or the first one after the base date (though without modifiers, you CAN make that assumption).
So, without modifiers, you might want to check:
($date1,$err) = $recur->nth(-1);
($date2,$err) = $recur->nth(0);
($date3,$err) = $recur->nth(1);
and one of those will meet your criteria. For a general solution, you'll need to do a loop:
date = recur->nth(0)
if (date < TARGET)
while (date2 = recur->next) {
if (date2 > TARGET)
date is the date you're looking for
else
date = date2
else
while (date2 = recur->prev) {
if (date2 < TARGET)
date2 is the date you're looking for
end
Assuming I haven't made a mistake in the algorithm, that's the fastest way because you test the minimum number of dates.
For a simpler solution, you could just do:
@date = $recur->dates(START,END)
where END is the date you are interested in and START is chosen to be sure that the recurrence will match at least 1 event - in the case of a monthly event, just make START be a couple months before END). Then the last date in the list will be the one you're interested in. Just remember that the START and END dates are inclusive.
Thank you very much for this very detailed explanation.
I went for the simpler solution, and it's working brilliantly.
I'm trying to get the first occurence of a recurring event before a given date.
Here is the code that I tried :
This should get "2nd Tuesday of every month" before the 28 aug 2017, which is the 8th of august.
But this code return the 11th of july, for whatever reason it goes straight to the previous month.
Am I missing something here, is there a way to do what I'm trying to do (get the first occurence before a given date) ?
Thanks.