From cdf2247047144ecd42c66acc4bbc1c4c49b2103f Mon Sep 17 00:00:00 2001 From: ralf Date: Tue, 6 Aug 2024 08:54:12 +0200 Subject: [PATCH] * Calendar: fix conflict check to take into account that whole-day (floating) events start and end by definition in all timezones at midnight and therefore must not conflict with other (non-floating) events starting or ending at midnight, but can conflict in other timezones (were the event to check does NOT start or end at midnight) --- calendar/inc/class.calendar_boupdate.inc.php | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/calendar/inc/class.calendar_boupdate.inc.php b/calendar/inc/class.calendar_boupdate.inc.php index 35e465bb67..38aa313edd 100644 --- a/calendar/inc/class.calendar_boupdate.inc.php +++ b/calendar/inc/class.calendar_boupdate.inc.php @@ -380,6 +380,13 @@ class calendar_boupdate extends calendar_bo $checked = 0; $start = microtime(true); $duration = Api\DateTime::to($event['end'], 'ts') - Api\DateTime::to($event['start'], 'ts'); + // as floating, whole-day events are defined as whole-day in user timezone (in fact in every TZ!), but they are + // always stored in server-timezone, we have to account for the difference, to not miss conflicts! + $start_tz_diff = Api\DateTime::$server_timezone->getOffset(new Api\DateTime($event['start'])) - + Api\DateTime::$user_timezone->getOffset(new Api\DateTime($event['start'])); + // might be different from $start_tz_diff, if TZ transition is during the event + $end_tz_diff = Api\DateTime::$server_timezone->getOffset(new Api\DateTime($event['end'])) - + Api\DateTime::$user_timezone->getOffset(new Api\DateTime($event['end'])); foreach($recurences as $date) { $startts = $date->format('ts'); @@ -402,8 +409,8 @@ class calendar_boupdate extends calendar_bo break; } $overlapping_events =& $this->search(array( - 'start' => $startts, - 'end' => $startts+$duration, + 'start' => $startts-abs($start_tz_diff), + 'end' => $startts+$duration+abs($end_tz_diff), 'users' => $users, 'ignore_acl' => true, // otherwise we get only events readable by the user 'enum_groups' => true, // otherwise group-events would not block time @@ -424,6 +431,11 @@ class calendar_boupdate extends calendar_bo { continue; } + // check if event is really blocking, as whole-day events use floating time and might NOT block in user's timezone + if ($overlap['end'] <= $startts || $overlap['start'] >= $startts+$duration) + { + continue; + } if ($this->debug > 3 || $this->debug == 'conflicts') { $this->debug_message(__METHOD__.'() checking overlapping event %1',false,$overlap);