diff --git a/lib/kolab_sync_data_tasks.php b/lib/kolab_sync_data_tasks.php --- a/lib/kolab_sync_data_tasks.php +++ b/lib/kolab_sync_data_tasks.php @@ -164,6 +164,23 @@ return $as_array ? $result : new Syncroton_Model_Task($result); } + + + /** + * Apply a timezone matching the utc offset. + */ + private static function applyTimezone($value, $utcValue) + { + $tzc = kolab_sync_timezone_converter::getInstance(); + $tz = $tzc->getOffsetTimezone($value, $utcValue); + if ($tz) { + //Setting the timezone will change the time, so we set it on the utc variant instead to end up with the same time in the new timezone. + $value = $utcValue; + $value->setTimezone($tz); + } + return $value; + } + /** * convert contact from xml to libkolab array * @@ -186,6 +203,23 @@ $value = $data->$key; switch ($name) { + + case 'due': + case 'start': + // We expect to always get regular and utc variants, so we only need to take one into account. + if ($key == 'utcStartDate' || $key == 'utcDueDate') { + continue 2; + } + if ($value) { + if ($name =='due' && $data->utcDueDate) { + $value = static::applyTimezone($value, $data->utcDueDate); + } + if ($name =='start' && $data->utcStartDate) { + $value = static::applyTimezone($value, $data->utcStartDate); + } + } + break; + case 'sensitivity': $map = array_flip($this->sensitivityMap); $value = $map[$value]; diff --git a/lib/kolab_sync_timezone_converter.php b/lib/kolab_sync_timezone_converter.php --- a/lib/kolab_sync_timezone_converter.php +++ b/lib/kolab_sync_timezone_converter.php @@ -87,6 +87,43 @@ return self::$_instance; } + + /** + * Returns a timezone with an offset matching the time difference + * of $dt from $referenceDt. + * + * If set and matching the offset, kolab_format::$timezone is preferred. + * + * @param DateTime $dt The date time value for which we + * calculate the offset. + * @param DateTime $referenceDt The reference value, for instance in UTC. + * + * @return DateTimeZone|null + */ + public function getOffsetTimezone($dt, $referenceDt) + { + $interval = $referenceDt->diff($dt); + $tz = new DateTimeZone($interval->format('%R%H%I')); //e.g. +0200 + $utcOffset = $tz->getOffset($dt); + + //Prefer the configured timezone if it matches the offset. + if (kolab_format::$timezone) { + if (kolab_format::$timezone->getOffset($dt) == $utcOffset) { + return kolab_format::$timezone; + } + } + + //Look for any timezone with a matching offset. + foreach (DateTimeZone::listIdentifiers() as $timezoneIdentifier) { + $timezone = new DateTimeZone($timezoneIdentifier); + if ($timezone->getOffset($dt) == $utcOffset) { + return $timezone; + } + } + return null; + } + + /** * Returns a list of timezones that match to the {@param $_offsets} *