diff --git a/application/Espo/Entities/Preferences.php b/application/Espo/Entities/Preferences.php index 61d0388dbc..68979d2eb4 100644 --- a/application/Espo/Entities/Preferences.php +++ b/application/Espo/Entities/Preferences.php @@ -42,4 +42,9 @@ class Preferences extends \Espo\Core\ORM\Entity { return null; } + + public function getTimeZone(): ?string + { + return $this->get('timeZone'); + } } diff --git a/application/Espo/Modules/Crm/Tools/Calendar/Service.php b/application/Espo/Modules/Crm/Tools/Calendar/Service.php index f40448d388..18f8ae3a91 100644 --- a/application/Espo/Modules/Crm/Tools/Calendar/Service.php +++ b/application/Espo/Modules/Crm/Tools/Calendar/Service.php @@ -29,6 +29,7 @@ namespace Espo\Modules\Crm\Tools\Calendar; +use DateTimeZone; use Espo\Core\Acl; use Espo\Core\Acl\Table; use Espo\Core\Exceptions\BadRequest; @@ -39,6 +40,7 @@ use Espo\Core\Field\DateTime as DateTimeField; use Espo\Core\Select\SelectBuilderFactory; use Espo\Core\Utils\Config; use Espo\Core\Utils\Metadata; +use Espo\Entities\Preferences; use Espo\Entities\Team; use Espo\Entities\User; use Espo\Modules\Crm\Entities\Call; @@ -891,18 +893,21 @@ class Service $from = $fetchParams->getFrom(); $to = $fetchParams->getTo(); + $timezone = !$fetchParams->isAgenda() ? + $this->getCurrentUserTimezone() : null; + $extractor = new Extractor(); $itemList = $fetchParams->workingTimeRangesInverted() ? ( $fetchParams->isAgenda() ? $extractor->extractInversion($calendar, $from, $to) : - $extractor->extractAllDayInversion($calendar, $from, $to) + $extractor->extractAllDayInversion($calendar, $from, $to, $timezone) ) : ( $fetchParams->isAgenda() ? $extractor->extract($calendar, $from, $to) : - $extractor->extractAllDay($calendar, $from, $to) + $extractor->extractAllDay($calendar, $from, $to, $timezone) ); $list = []; @@ -1015,4 +1020,29 @@ class Service return $result; } + + private function getCurrentUserTimezone(): DateTimeZone + { + try { + return new DateTimeZone($this->getCurrentUserTimezoneString()); + } catch (Exception $e) { + throw new RuntimeException($e->getMessage(), 0, $e); + } + } + + /** + * @todo Move to a separate class. + */ + private function getCurrentUserTimezoneString(): string + { + $preferences = $this->entityManager + ->getRepositoryByClass(Preferences::class) + ->getById($this->user->getId()); + + if ($preferences && $preferences->getTimeZone()) { + return $preferences->getTimeZone(); + } + + return $this->config->get('timeZone') ?? 'UTC'; + } } diff --git a/application/Espo/Tools/WorkingTime/Extractor.php b/application/Espo/Tools/WorkingTime/Extractor.php index befe4b00dd..aa1db5a72f 100644 --- a/application/Espo/Tools/WorkingTime/Extractor.php +++ b/application/Espo/Tools/WorkingTime/Extractor.php @@ -29,6 +29,7 @@ namespace Espo\Tools\WorkingTime; +use DateTimeZone; use Espo\Tools\WorkingTime\Calendar\WorkingWeekday; use Espo\Tools\WorkingTime\Calendar\WorkingDate; use Espo\Tools\WorkingTime\Calendar\HavingRanges; @@ -137,10 +138,16 @@ class Extractor /** * @return array{DateTime,DateTime}[] */ - public function extractAllDay(Calendar $calendar, DateTime $from, DateTime $to): array - { + public function extractAllDay(Calendar $calendar, + DateTime $from, + DateTime $to, + ?DateTimeZone $timezone = null + ): array { + + $timezone ??= $calendar->getTimezone(); + $pointer = $from - ->withTimezone($calendar->getTimezone()) + ->withTimezone($timezone) ->withTime(0, 0, 0); $fromDate = Date::fromDateTime($from->modify('-1 day')->toDateTime()); @@ -152,7 +159,7 @@ class Extractor $list = []; - $end = $to->withTimezone($calendar->getTimezone())->withTime(23, 59, 59); + $end = $to->withTimezone($timezone)->withTime(23, 59, 59); while ($pointer->toTimestamp() < $end->toTimestamp()) { $isWorkingDay = $this->isWorkingDay( @@ -225,9 +232,14 @@ class Extractor /** * @return array{DateTime,DateTime}[] */ - public function extractAllDayInversion(Calendar $calendar, DateTime $from, DateTime $to): array - { - $list = $this->extractAllDay($calendar, $from, $to); + public function extractAllDayInversion( + Calendar $calendar, + DateTime $from, + DateTime $to, + ?DateTimeZone $timezone = null + ): array { + + $list = $this->extractAllDay($calendar, $from, $to, $timezone); if ($list === []) { return [[$from, $to]];