I tackled a similar issue at work just a couple months ago. Basically what I did was just store how the reptition was going to be done (daily weekly etc.). I didn't break it down to be every other, every 3rd every 4th etc.; however, I did have bi-weekly items.
Anyway, the trick is to really think about what you're doing. Most of this stuff can't be done with straight addition of 7 to the day; well, for my purposes it couldn't (monthly views 3 months in advance or whatever). So I created a function that got the day name of the date the event is for (Sunday for 7/22/07) and then used that to determine which numerical date the first X-day (in this case Sunday) was. Once I had that, I could just add 7, 14 or whatever to do the repeats.
function getFirstDay($month, $day, $year)
{
$timegiven = mktime(0, 0, 0, $month, 1, $year);
$day = ($day - date('w', $timegiven)) + 1;
if($day < 1) { $day += 7; }
return $day;
}
Basically, you look send the date('w') of the start-date, then you create a unix timestamp of the first day of the desired month. Then you take the $day, and subtract it from the date('w') of the desired month, and add 1 (because the first day of any month is not "0"). Now, if the number is negative (as in the first of the month is past the desired week-day, then you add 7 to get the first date of the desired weekday.
Here's an example:
-
July 11, 2007 was a Wednesday (Wednesday is day number "3" [0=>Sunday, 1=>Monday...])
-
An event happening every week on Wednesdays is created on July 11, 2007
-
We are looking at a calendar of August 2008
-
We are assuming this weekly Wednesday event is recurring indefinitely
-
The first day of August 2008 is a Friday (Friday is day number "5")
-
We subtract 5 from 3 (3 - 5) = -2
-
We add 1 because no month starts on date "0": -2+1 = -1
-
Now, because the number is less than 1, we add 7 to get the date of the first Wednesday of August 2008: -1 + 7 = 6
-
August 6, 2008 is the first Wednesday of the month.
Hope that makes sense in some way.
Now, to deal with bi-weekly events, I got the first Xday of the viewed month, and created a unix timestamp with it. Then I subtracted the unix timestamp of the event date. If the difference was greater-than 0, I took the difference, divided by 1 weeks worth of seconds (604800) and then used the modulus operator to see if it was even or odd ($diff/604800)%2==0). If it was even, then we use the first week; otherwise, we use the second week.
$tmp = date('w', strtotime($event_date));
$firstDay = getFirstDay($month, $tmp, $year);
$diff = strtotime($year.'-'.$month.'-'.$firstDay) - strtotime($event_date);
if($diff > 0)
{
$offset = ((floor($diff/604800)%2) != 0);
$start = ($offset) ? $firstDay+7 : $firstDay;
}
else
$start = date('j', $event_date);
Then it's just a matter of looping through $i=1; $i<$days_in_month; $i+14 and adding those events to the calendar.
Hopefully you can use this to help you adapt it to your needs.