diff --git a/plugins/libcalendaring/libvcalendar.php b/plugins/libcalendaring/libvcalendar.php index 4f53494a..164d1841 100644 --- a/plugins/libcalendaring/libvcalendar.php +++ b/plugins/libcalendaring/libvcalendar.php @@ -1309,12 +1309,15 @@ class libvcalendar implements Iterator * @param string Timezone ID as used in PHP's Date functions * @param integer Unix timestamp with first date/time in this timezone * @param integer Unix timestap with last date/time in this timezone + * @param VObject\Component\VCalendar Optional VCalendar component * * @return mixed A Sabre\VObject\Component object representing a VTIMEZONE definition * or false if no timezone information is available */ public static function get_vtimezone($tzid, $from = 0, $to = 0, $cal = null) { + // TODO: Consider using tzurl.org database for better interoperability e.g. with Outlook + if (!$from) $from = time(); if (!$to) $to = $from; if (!$cal) $cal = new VObject\Component\VCalendar(); @@ -1338,6 +1341,17 @@ class libvcalendar implements Iterator $year = 86400 * 360; $transitions = $tz->getTransitions($from - $year, $to + $year); + // Make sure VTIMEZONE contains at least one STANDARD/DAYLIGHT component + // when there's only one transition in specified time period (T5626) + if (count($transitions) == 1) { + // Get more transitions and use OFFSET from the previous to last + $more_transitions = $tz->getTransitions(0, $to + $year); + if (count($more_transitions) > 1) { + $index = count($more_transitions) - 2; + $tzfrom = $more_transitions[$index]['offset'] / 3600; + } + } + $vt = $cal->createComponent('VTIMEZONE'); $vt->TZID = $tz->getName(); @@ -1345,7 +1359,7 @@ class libvcalendar implements Iterator foreach ($transitions as $i => $trans) { $cmp = null; - if ($i == 0) { + if (!isset($tzfrom)) { $tzfrom = $trans['offset'] / 3600; continue; } diff --git a/plugins/libcalendaring/tests/libvcalendar.php b/plugins/libcalendaring/tests/libvcalendar.php index c181dcd9..29f73520 100644 --- a/plugins/libcalendaring/tests/libvcalendar.php +++ b/plugins/libcalendaring/tests/libvcalendar.php @@ -581,6 +581,25 @@ class libvcalendar_test extends PHPUnit_Framework_TestCase $this->assertInstanceOf('\Sabre\VObject\Component', $vtz); $this->assertContains('TZOFFSETFROM:+1245', $vtz->serialize()); $this->assertContains('TZOFFSETTO:+1345', $vtz->serialize()); + + // Making sure VTIMEZOONE contains at least one STANDARD/DAYLIGHT component + // when there's only one transition in specified time period (T5626) + $vtz = libvcalendar::get_vtimezone('Europe/Istanbul', strtotime('2019-10-04T15:00:00')); + + $this->assertInstanceOf('\Sabre\VObject\Component', $vtz); + + $dst = $vtz->select('DAYLIGHT'); + $std = $vtz->select('STANDARD'); + + $this->assertEmpty($dst); + $this->assertCount(1, $std); + + $std = end($std); + $this->assertEquals('STANDARD', $std->name); + $this->assertEquals('20181009T150000', $std->DTSTART); + $this->assertEquals('+0300', $std->TZOFFSETFROM); + $this->assertEquals('+0300', $std->TZOFFSETTO); + $this->assertEquals('+03', $std->TZNAME); } function get_attachment_data($id, $event) @@ -588,4 +607,3 @@ class libvcalendar_test extends PHPUnit_Framework_TestCase return $this->attachment_data; } } -