195 lines
5.6 KiB
PHP
195 lines
5.6 KiB
PHP
<?php
|
|
/**
|
|
* Copyright 2003-2017 Horde LLC (http://www.horde.org/)
|
|
*
|
|
* See the enclosed file COPYING for license information (LGPL). If you
|
|
* did not receive this file, see http://www.horde.org/licenses/lgpl21.
|
|
*
|
|
* @author Mike Cochrane <mike@graftonhall.co.nz>
|
|
* @category Horde
|
|
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
|
* @package Icalendar
|
|
*/
|
|
|
|
/**
|
|
* Class representing vTimezones.
|
|
*
|
|
* @author Mike Cochrane <mike@graftonhall.co.nz>
|
|
* @category Horde
|
|
* @copyright 2003-2017 Horde LLC
|
|
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
|
|
* @package Icalendar
|
|
*/
|
|
class Horde_Icalendar_Vtimezone extends Horde_Icalendar
|
|
{
|
|
/**
|
|
* The component type of this class.
|
|
*
|
|
* @var string
|
|
*/
|
|
public $type = 'vTimeZone';
|
|
|
|
/**
|
|
* TODO
|
|
*
|
|
* @return TODO
|
|
*/
|
|
public function exportvCalendar()
|
|
{
|
|
return $this->_exportvData('VTIMEZONE');
|
|
}
|
|
|
|
/**
|
|
* Parses child components of vTimezone component.
|
|
*
|
|
* Returns an array with the exact time of the time change as well as the
|
|
* 'from' and 'to' offsets around the change. Time is arbitrarily based on
|
|
* UTC for comparison.
|
|
*
|
|
* @param Horde_Icalendar_Standard|Horde_Icalendar_Daylight $child
|
|
* A timezone component.
|
|
* @param integer $year
|
|
* The latest year we are interested in.
|
|
*
|
|
* @return array A list of hashes with "time", "from", and "to" elements.
|
|
*/
|
|
public function parseChild($child, $year)
|
|
{
|
|
$result['time'] = $result['end'] = 0;
|
|
|
|
try {
|
|
$t = $child->getAttribute('TZOFFSETFROM');
|
|
} catch (Horde_Icalendar_Exception $e) {
|
|
return array();
|
|
}
|
|
$result['from'] = ($t['hour'] * 60 * 60 + $t['minute'] * 60) * ($t['ahead'] ? 1 : -1);
|
|
|
|
try {
|
|
$t = $child->getAttribute('TZOFFSETTO');
|
|
} catch (Horde_Icalendar_Exception $e) {
|
|
return array();
|
|
}
|
|
$result['to'] = ($t['hour'] * 60 * 60 + $t['minute'] * 60) * ($t['ahead'] ? 1 : -1);
|
|
|
|
try {
|
|
$start = $child->getAttribute('DTSTART');
|
|
} catch (Horde_Icalendar_Exception $e) {
|
|
return array();
|
|
}
|
|
if (!is_int($start)) {
|
|
return array();
|
|
}
|
|
$start = getdate($start);
|
|
if ($start['year'] > $year) {
|
|
return array();
|
|
}
|
|
|
|
$results = array();
|
|
try {
|
|
$rdates = $child->getAttributeValues('RDATE');
|
|
foreach ($rdates as $rdate) {
|
|
if ($rdate['year'] == $year || $rdate['year'] == $year - 1) {
|
|
$result['time'] = $result['end'] = gmmktime(
|
|
$start['hours'], $start['minutes'], $start['seconds'],
|
|
$rdate['month'], $rdate['mday'], $rdate['year']
|
|
);
|
|
$results[] = $result;
|
|
}
|
|
}
|
|
} catch (Horde_Icalendar_Exception $e) {
|
|
}
|
|
|
|
try {
|
|
$rrules = $child->getAttribute('RRULE');
|
|
} catch (Horde_Icalendar_Exception $e) {
|
|
if (!$results) {
|
|
$result['time'] = $result['end'] = $start[0];
|
|
$results[] = $result;
|
|
}
|
|
return $results;
|
|
}
|
|
|
|
$rrules = explode(';', $rrules);
|
|
foreach ($rrules as $rrule) {
|
|
$t = explode('=', $rrule);
|
|
switch ($t[0]) {
|
|
case 'FREQ':
|
|
if ($t[1] != 'YEARLY') {
|
|
return array();
|
|
}
|
|
break;
|
|
|
|
case 'INTERVAL':
|
|
if ($t[1] != '1') {
|
|
return array();
|
|
}
|
|
break;
|
|
|
|
case 'BYMONTH':
|
|
$month = intval($t[1]);
|
|
break;
|
|
|
|
case 'BYDAY':
|
|
$len = strspn($t[1], '1234567890-+');
|
|
if ($len == 0) {
|
|
return array();
|
|
}
|
|
$weekday = substr($t[1], $len);
|
|
$weekdays = array(
|
|
'SU' => 0,
|
|
'MO' => 1,
|
|
'TU' => 2,
|
|
'WE' => 3,
|
|
'TH' => 4,
|
|
'FR' => 5,
|
|
'SA' => 6
|
|
);
|
|
$weekday = $weekdays[$weekday];
|
|
$which = intval(substr($t[1], 0, $len));
|
|
break;
|
|
|
|
case 'UNTIL':
|
|
$result['end'] = intval(substr($t[1], 0, 4));
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (empty($month) || !isset($weekday)) {
|
|
return array();
|
|
}
|
|
|
|
// Get the timestamp for the first day of $month.
|
|
if ($result['end'] && $year > $result['end']) {
|
|
$year = $result['end'];
|
|
}
|
|
|
|
$when = gmmktime($start['hours'], $start['minutes'], $start['seconds'],
|
|
$month, 1, $year);
|
|
// Get the day of the week for the first day of $month.
|
|
$first_of_month_weekday = intval(gmstrftime('%w', $when));
|
|
|
|
// Go to the first $weekday before first day of $month.
|
|
if ($weekday >= $first_of_month_weekday) {
|
|
$weekday -= 7;
|
|
}
|
|
$when -= ($first_of_month_weekday - $weekday) * 60 * 60 * 24;
|
|
|
|
// If going backwards go to the first $weekday after last day
|
|
// of $month.
|
|
if ($which < 0) {
|
|
do {
|
|
$when += 60 * 60 * 24 * 7;
|
|
} while (intval(gmstrftime('%m', $when)) == $month);
|
|
}
|
|
|
|
// Calculate $weekday number $which.
|
|
$when += $which * 60 * 60 * 24 * 7;
|
|
|
|
$result['time'] = $when;
|
|
$results[] = $result;
|
|
|
|
return $results;
|
|
}
|
|
|
|
}
|