Skip to content

Commit

Permalink
BYSETPOS now supported
Browse files Browse the repository at this point in the history
Fix to ensure our manually calculated until date from COUNT covers
ending on the same day as the rule began should the relevant type of
rule be defined
Duplicated code moved to only be defined once
Frequency now defined as a reusable var
  • Loading branch information
u01jmg3 committed Apr 21, 2015
1 parent 5aae755 commit 4d4fbd1
Showing 1 changed file with 36 additions and 15 deletions.
51 changes: 36 additions & 15 deletions class.iCalReader.php
Original file line number Diff line number Diff line change
Expand Up @@ -258,13 +258,31 @@ public function process_recurrences()
list($k, $v) = explode('=', $s);
$rrules[$k] = $v;
}
// Get frequency
$frequency = $rrules['FREQ'];
// Get Start timestamp
$start_timestamp = $this->iCalDateToUnixTimestamp($anEvent['DTSTART']);
$end_timestamp = $this->iCalDateToUnixTimestamp($anEvent['DTEND']);
$event_timestmap_offset = $end_timestamp - $start_timestamp;
// Get Interval
$interval = (isset($rrules['INTERVAL']) && $rrules['INTERVAL'] != '') ? $rrules['INTERVAL'] : 1;

if (in_array($frequency, array('MONTHLY', 'YEARLY')) && isset($rrules['BYDAY']) && $rrules['BYDAY'] != '') {
// Deal with BYDAY
$day_number = intval($rrules['BYDAY']);
if (empty($day_number)) { // Returns 0 when no number defined in BYDAY
if (!isset($rrules['BYSETPOS'])) {
$day_number = 1; // Set first as default
} else if (is_numeric($rrules['BYSETPOS'])) {
$day_number = $rrules['BYSETPOS'];
}
}
$day_number = ($day_number == -1) ? 6 : $day_number; // Override for our custom key (6 => 'last')
$week_day = substr($rrules['BYDAY'], -2);
$day_ordinals = array(1 => 'first', 2 => 'second', 3 => 'third', 4 => 'fourth', 5 => 'fifth', 6 => 'last');
$weekdays = array('SU' => 'sunday', 'MO' => 'monday', 'TU' => 'tuesday', 'WE' => 'wednesday', 'TH' => 'thursday', 'FR' => 'friday', 'SA' => 'saturday');
}

$until_default = date_create('now');
$until_default->modify($this->default_span . ' year');
$until_default->setTime(23, 59, 59); // End of the day
Expand All @@ -278,15 +296,30 @@ public function process_recurrences()
$count_orig = (is_numeric($rrules['COUNT']) && $rrules['COUNT'] > 1) ? $rrules['COUNT'] : 0;
$count = ($count_orig - 1); // Remove one to exclude the occurrence that initialises the rule
$count += ($count > 0) ? $count * ($interval - 1) : 0;
$offset = "+$count " . $frequency_conversion[$rrules['FREQ']];
$offset = "+$count " . $frequency_conversion[$frequency];
$until = strtotime($offset, $start_timestamp);

if (in_array($frequency, array('MONTHLY', 'YEARLY')) && isset($rrules['BYDAY']) && $rrules['BYDAY'] != '') {
$dtstart = date_create($anEvent['DTSTART']);
for ($i = 1; $i <= $count; $i++) {
$dtstart_clone = clone $dtstart;
$dtstart_clone->modify('next ' . $frequency_conversion[$frequency]);
$offset = "{$day_ordinals[$day_number]} {$weekdays[$week_day]} of " . $dtstart_clone->format('F Y H:i:01');
$dtstart->modify($offset);
}

// Jumping X months forwards doesn't mean the end date will fall on the same day defined in BYDAY
// Use the largest of these to ensure we are going far enough in the future to capture our final end day
$until = max($until, $dtstart->format('U'));
}

unset($offset);
} else {
$until = $this->iCalDateToUnixTimestamp($until_default);
}

// Decide how often to add events and do so
switch ($rrules['FREQ']) {
switch ($frequency) {
case 'DAILY':
// Simply add a new event each interval of days until UNTIL is reached
$offset = "+$interval day";
Expand Down Expand Up @@ -358,12 +391,6 @@ public function process_recurrences()
}
} else if (isset($rrules['BYDAY']) && $rrules['BYDAY'] != '') {
$start_time = date('His', $start_timestamp);
// Deal with BYDAY
$day_number = intval($rrules['BYDAY']);
$day_number = ($day_number == -1) ? 0 : 1;
$week_day = substr($rrules['BYDAY'], -2);
$day_ordinals = array(0 => 'last', 1 => 'first', 2 => 'second', 3 => 'third', 4 => 'fourth', 5 => 'fifth');
$weekdays = array('SU' => 'sunday', 'MO' => 'monday', 'TU' => 'tuesday', 'WE' => 'wednesday', 'TH' => 'thursday', 'FR' => 'friday', 'SA' => 'saturday');
while ($recurring_timestamp <= $until) {
$event_start_desc = "{$day_ordinals[$day_number]} {$weekdays[$week_day]} of " . date('F Y H:i:s', $recurring_timestamp);
$event_start_timestamp = strtotime($event_start_desc);
Expand All @@ -387,14 +414,8 @@ public function process_recurrences()
// Check if BYDAY rule exists
if (isset($rrules['BYDAY']) && $rrules['BYDAY'] != '') {
$start_time = date('His', $start_timestamp);
// Deal with BYDAY
$day_number = intval($rrules['BYDAY']);
$day_number = ($day_number == -1) ? 0 : 1;
$month_day = substr($rrules['BYDAY'], -2);
$day_ordinals = array(0 => 'last', 1 => 'first', 2 => 'second', 3 => 'third', 4 => 'fourth', 5 => 'fifth');
$weekdays = array('SU' => 'sunday', 'MO' => 'monday', 'TU' => 'tuesday', 'WE' => 'wednesday', 'TH' => 'thursday', 'FR' => 'friday', 'SA' => 'saturday');
while ($recurring_timestamp <= $until) {
$event_start_desc = "{$day_ordinals[$day_number]} {$weekdays[$month_day]} of {$month_names[$rrules['BYMONTH']]} " . date('Y H:i:s', $recurring_timestamp);
$event_start_desc = "{$day_ordinals[$day_number]} {$weekdays[$week_day]} of {$month_names[$rrules['BYMONTH']]} " . date('Y H:i:s', $recurring_timestamp);
$event_start_timestamp = strtotime($event_start_desc);
if ($event_start_timestamp > $start_timestamp && $event_start_timestamp < $until) {
$anEvent['DTSTART'] = date('Ymd\T', $event_start_timestamp) . $start_time;
Expand Down

0 comments on commit 4d4fbd1

Please sign in to comment.