Skip to content

Commit 1aa4d18

Browse files
committed
Ensure start date for exceptions take overrides into account (fixes #18)
1 parent fe59bc8 commit 1aa4d18

File tree

1 file changed

+49
-1
lines changed

1 file changed

+49
-1
lines changed

src/Calendar.php

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -298,7 +298,8 @@ protected function normalize_exceptions(array $event) : array {
298298
// granularity based on frequencty, so that RRULE can properly parse
299299
// exception times.
300300
$aligned = array_map(function($exception) use ($event, $rules) {
301-
return $this->align_time($exception, $event['start'], $rules['frequency']);
301+
$event_start_with_override = $this->get_event_start_with_overrides($exception, $event);
302+
return $this->align_time($exception, $event_start_with_override, $rules['frequency']);
302303
}, $normalized);
303304

304305
// Filter out empty values, which could have been returned by parsing a
@@ -342,4 +343,51 @@ public function align_time(string $dt, string $start, string $freq) {
342343
$start_str = gmdate($start_fmt, strtotime($start) ?: 0);
343344
return date_create_immutable($dt_str . $start_str);
344345
}
346+
347+
/**
348+
* Given a target occurrence date string and an event, get the start date and time
349+
* string, with any applicable override applied.
350+
*
351+
* @param string $dt The target event occurrence date string, formatted Y-m-d H:i:s
352+
* @param array $event The event data array, including recurrence data
353+
*
354+
* @return string The start date of the event on the target date, possibly with the
355+
* time overridden
356+
*/
357+
public function get_event_start_with_overrides(string $dt, array $event) {
358+
// Start with the original start datetime
359+
$start = $event['start'];
360+
$overrides = $event['recurrence']['overrides'] ?? [];
361+
362+
if ($overrides) {
363+
$days_of_week = [
364+
1 => 'MO',
365+
2 => 'TU',
366+
3 => 'WE',
367+
4 => 'TH',
368+
5 => 'FR',
369+
6 => 'SA',
370+
7 => 'SU',
371+
];
372+
$dt_object = \DateTime::createFromFormat('Y-m-d H:i:s', $dt);
373+
$dt_day_of_week = $dt_object->format('N');
374+
$dt_day_of_week_code = $days_of_week[$dt_day_of_week];
375+
$applicable_overrides = array_values(
376+
array_filter(
377+
$overrides,
378+
function ($override) use ($dt_day_of_week_code) {
379+
return in_array($dt_day_of_week_code, $override['BYDAY'] ?? []);
380+
}
381+
)
382+
);
383+
384+
// Change the start datetime based on the override we found
385+
if ($applicable_overrides) {
386+
$override_time = $applicable_overrides[0]['start'];
387+
$start = $dt_object->format('Y-m-d') . ' ' . $override_time;
388+
}
389+
}
390+
391+
return $start;
392+
}
345393
}

0 commit comments

Comments
 (0)