Adds TZID/VTIMEZONE support for server timezone entries

This commit is contained in:
Jörg Lehrke 2009-10-05 21:00:08 +00:00
parent b5673ab38a
commit 1353ae511a

View File

@ -192,14 +192,6 @@ class calendar_ical extends calendar_boupdate
$version = '2.0'; $version = '2.0';
} }
$servertime = false;
$date_format = 'server';
if (strpos($this->productName, "palmos") )
{
$servertime = true;
$date_format = 'ts';
}
$vcal = new Horde_iCalendar; $vcal = new Horde_iCalendar;
$vcal->setAttribute('PRODID','-//eGroupWare//NONSGML eGroupWare Calendar '.$GLOBALS['egw_info']['apps']['calendar']['version'].'//'. $vcal->setAttribute('PRODID','-//eGroupWare//NONSGML eGroupWare Calendar '.$GLOBALS['egw_info']['apps']['calendar']['version'].'//'.
strtoupper($GLOBALS['egw_info']['user']['preferences']['common']['lang'])); strtoupper($GLOBALS['egw_info']['user']['preferences']['common']['lang']));
@ -210,10 +202,18 @@ class calendar_ical extends calendar_boupdate
while (($event = array_pop($events))) while (($event = array_pop($events)))
{ {
if (strpos($this->productName, 'palmos'))
{
$servertime = true;
$date_format = 'ts';
}
else
{
$servertime = false;
}
if (!is_array($event) if (!is_array($event)
&& !($event = $this->read($event, $recur_date, false, $date_format))) && !($event = $this->read($event, $recur_date, false, $date_format)))
{ {
// server = timestamp in server-time(!)
return false; // no permission to read $cal_id return false; // no permission to read $cal_id
} }
if ($recur_date) if ($recur_date)
@ -225,17 +225,25 @@ class calendar_ical extends calendar_boupdate
} }
$event['recur_type'] = MCAL_RECUR_NONE; $event['recur_type'] = MCAL_RECUR_NONE;
} }
//_debug_array($event);
// correct daylight saving time if ($this->log) error_log(__FILE__.'('.__LINE__.'): '.__METHOD__.' '.array2string($event)."\n",3,$this->logfile);
/* causes times wrong by one hour, if exporting events with DST different from the current date,
which this fix is suppost to fix. Maybe the problem has been fixed in the horde code too. if (!$servertime && $event['recur_type'] != MCAL_RECUR_NONE)
$currentDST = date('I', mktime()); {
$eventDST = date('I', $event['start']); if ($event['recur_enddate'])
$DSTCorrection = ($currentDST - $eventDST) * 3600; {
$event['start'] = $event['start'] + $DSTCorrection; $startDST = date('I', $event['start']);
$event['end'] = $event['end'] + $DSTCorrection; $finalDST = date('I', $event['recur_enddate']);
*/ // Different DST or more than half a year?
if ($startDST != $finalDST ||
($event['recur_enddate'] - $event['start']) > 15778800)
{
$servertime = true;
// read the event again with timestamps
$event = $this->read($event['id'], 0, false, 'ts');
}
}
}
if ($this->productManufacturer != 'file' && $this->uidExtension) if ($this->productManufacturer != 'file' && $this->uidExtension)
{ {
@ -248,6 +256,15 @@ class calendar_ical extends calendar_boupdate
$vevent = Horde_iCalendar::newComponent('VEVENT', $vcal); $vevent = Horde_iCalendar::newComponent('VEVENT', $vcal);
$parameters = $attributes = $values = array(); $parameters = $attributes = $values = array();
if ($servertime)
{
$serverTZ = $this->generate_vtimezone($event['start'], $vevent);
}
else
{
$serverTZ = null;
}
if ($this->productManufacturer == 'sonyericsson') if ($this->productManufacturer == 'sonyericsson')
{ {
$eventDST = date('I', $event['start']); $eventDST = date('I', $event['start']);
@ -324,6 +341,7 @@ class calendar_ical extends calendar_boupdate
if ($servertime) if ($servertime)
{ {
$attributes['DTSTART'] = date('Ymd\THis', $event['start']); $attributes['DTSTART'] = date('Ymd\THis', $event['start']);
if ($serverTZ) $parameters['DTSTART']['TZID'] = $serverTZ;
} }
else else
{ {
@ -349,6 +367,7 @@ class calendar_ical extends calendar_boupdate
if ($servertime) if ($servertime)
{ {
$attributes['DTEND'] = date('Ymd\THis', $event['end']); $attributes['DTEND'] = date('Ymd\THis', $event['end']);
if ($serverTZ) $parameters['DTEND']['TZID'] = $serverTZ;
} }
else else
{ {
@ -388,15 +407,8 @@ class calendar_ical extends calendar_boupdate
{ {
$recur_enddate = (int)$event['recur_enddate']; $recur_enddate = (int)$event['recur_enddate'];
$recur_enddate += 24 * 60 * 60 - 1; $recur_enddate += 24 * 60 * 60 - 1;
if ($servertime)
{
$rrule['UNTIL'] = date('Ymd\THis', $recur_enddate);
}
else
{
$rrule['UNTIL'] = $vcal->_exportDateTime($recur_enddate); $rrule['UNTIL'] = $vcal->_exportDateTime($recur_enddate);
} }
}
else else
{ {
$rrule['UNTIL'] = '#0'; $rrule['UNTIL'] = '#0';
@ -439,17 +451,10 @@ class calendar_ical extends calendar_boupdate
$rrule['UNTIL'] = date('Ymd', $recur_enddate); $rrule['UNTIL'] = date('Ymd', $recur_enddate);
} }
else else
{
if ($servertime)
{
$rrule['UNTIL'] = date('Ymd\THis', $recur_enddate);
}
else
{ {
$rrule['UNTIL'] = $vcal->_exportDateTime($recur_enddate); $rrule['UNTIL'] = $vcal->_exportDateTime($recur_enddate);
} }
} }
}
// no idea how to get the Horde parser to produce a standard conformant // no idea how to get the Horde parser to produce a standard conformant
// RRULE:FREQ=... (note the double colon after RRULE, we cant use the $parameter array) // RRULE:FREQ=... (note the double colon after RRULE, we cant use the $parameter array)
// so we create one value manual ;-) // so we create one value manual ;-)
@ -528,6 +533,7 @@ class calendar_ical extends calendar_boupdate
} }
$attributes['EXDATE'] = ''; $attributes['EXDATE'] = '';
$values['EXDATE'] = $days; $values['EXDATE'] = $days;
if ($serverTZ) $parameters['EXDATE']['TZID'] = $serverTZ;
$parameters['EXDATE']['VALUE'] = $value_type; $parameters['EXDATE']['VALUE'] = $value_type;
} }
break; break;
@ -571,6 +577,7 @@ class calendar_ical extends calendar_boupdate
if ($servertime) if ($servertime)
{ {
$attributes['RECURRENCE-ID'] = date('Ymd\THis', $recur_date); $attributes['RECURRENCE-ID'] = date('Ymd\THis', $recur_date);
if ($serverTZ) $parameters['RECURRENCE-ID']['TZID'] = $serverTZ;
} }
else else
{ {
@ -598,6 +605,7 @@ class calendar_ical extends calendar_boupdate
if ($servertime) if ($servertime)
{ {
$attributes['RECURRENCE-ID'] = date('Ymd\THis', $event['recurrence']); $attributes['RECURRENCE-ID'] = date('Ymd\THis', $event['recurrence']);
if ($serverTZ) $parameters['RECURRENCE-ID']['TZID'] = $serverTZ;
} }
else else
{ {
@ -654,36 +662,15 @@ class calendar_ical extends calendar_boupdate
$created = $GLOBALS['egw']->contenthistory->getTSforAction('calendar',$event['id'],'add'); $created = $GLOBALS['egw']->contenthistory->getTSforAction('calendar',$event['id'],'add');
if (!$created && !$modified) $created = $event['modified']; if (!$created && !$modified) $created = $event['modified'];
if ($created) if ($created)
{
if ($servertime)
{
$attributes['CREATED'] = date('Ymd\THis', $created);
}
else
{ {
$attributes['CREATED'] = $created; $attributes['CREATED'] = $created;
} }
}
if (!$modified) $modified = $event['modified']; if (!$modified) $modified = $event['modified'];
if ($modified) if ($modified)
{
if ($servertime)
{
$attributes['LAST-MODIFIED'] = date('Ymd\THis', $modified);
}
else
{ {
$attributes['LAST-MODIFIED'] = $modified; $attributes['LAST-MODIFIED'] = $modified;
} }
}
if ($servertime)
{
$attributes['DTSTAMP'] = date('Ymd\THis', time());
}
else
{
$attributes['DTSTAMP'] = time(); $attributes['DTSTAMP'] = time();
}
foreach($event['alarm'] as $alarmID => $alarmData) foreach($event['alarm'] as $alarmID => $alarmData)
{ {
// skip alarms being set for all users or alarms owned by other users // skip alarms being set for all users or alarms owned by other users
@ -697,7 +684,9 @@ class calendar_ical extends calendar_boupdate
if ($servertime) if ($servertime)
{ {
$attributes['DALARM'] = date('Ymd\THis', $alarmData['time']); $attributes['DALARM'] = date('Ymd\THis', $alarmData['time']);
if ($serverTZ) $parameters['DALARM']['TZID'] = $serverTZ;
$attributes['AALARM'] = date('Ymd\THis', $alarmData['time']); $attributes['AALARM'] = date('Ymd\THis', $alarmData['time']);
if ($serverTZ) $parameters['AALARM']['TZID'] = $serverTZ;
} }
else else
{ {
@ -719,6 +708,12 @@ class calendar_ical extends calendar_boupdate
// RFC requires DESCRIPTION for DISPLAY // RFC requires DESCRIPTION for DISPLAY
if (!$event['title'] && !$description) continue; if (!$event['title'] && !$description) continue;
if ($this->isWholeDay($event) && $alarmData['offset'])
{
$alarmData['time'] = $event['start'] - $alarmData['offset'];
$alarmData['offset'] = false;
}
$valarm = Horde_iCalendar::newComponent('VALARM',$vevent); $valarm = Horde_iCalendar::newComponent('VALARM',$vevent);
if ($alarmData['offset']) if ($alarmData['offset'])
{ {
@ -727,15 +722,17 @@ class calendar_ical extends calendar_boupdate
} }
else else
{ {
$params = array('VALUE' => 'DATE-TIME');
if ($servertime) if ($servertime)
{ {
$value = date('Ymd\THis', $alarmData['time']); $value = date('Ymd\THis', $alarmData['time']);
if ($serverTZ) $params['TZID'] = $serverTZ;
} }
else else
{ {
$value = $alarmData['time']; $value = $alarmData['time'];
} }
$valarm->setAttribute('TRIGGER', $value, array('VALUE' => 'DATE-TIME')); $valarm->setAttribute('TRIGGER', $value, $params);
} }
$valarm->setAttribute('ACTION','DISPLAY'); $valarm->setAttribute('ACTION','DISPLAY');
@ -2258,4 +2255,297 @@ class calendar_ical extends calendar_boupdate
'master_event' => $return_master ? $master_event : false, 'master_event' => $return_master ? $master_event : false,
); );
} }
/**
* generate and insert a VTIMEZONE entry for an event
*
* @param int $ts timestamp to evaluate the local timezone and year
* @param array $vevent VEVENT representation of the event
* @return string local timezone name (e.g. 'CET/CEST')
*/
function generate_vtimezone($ts, &$vevent)
{
$utc = array('UTC',null,0,0,"",0,0,0,0,0,0,0,0,0,0);
$dayofweek = array('SU','MO','TU','WE','TH','FR','SA');
$tbl_tz = array(
array("Afghanistan","Asia/Kabul",270,0,"",0,0,0,0,0,0,0,0,0,0),
array("AKST/AKDT","America/Anchorage",-540,60,"",3,0,2,2,0,11,0,1,2,0),
array("AKST/AKDT","America/Anchorage",-540,60,"2006",4,0,1,2,0,10,0,5,2,0),
array("AKST/AKDT","America/Anchorage",-540,60,"2007",3,0,2,2,0,11,0,1,2,0),
array("HNY/NAY","America/Anchorage",-540,60,"",3,0,2,2,0,11,0,1,2,0),
array("HNY/NAY","America/Anchorage",-540,60,"2006",4,0,1,2,0,10,0,5,2,0),
array("HNY/NAY","America/Anchorage",-540,60,"2007",3,0,2,2,0,11,0,1,2,0),
array("Alaskan","America/Anchorage",-540,60,"",3,0,2,2,0,11,0,1,2,0),
array("Alaskan","America/Anchorage",-540,60,"2006",4,0,1,2,0,10,0,5,2,0),
array("Alaskan","America/Anchorage",-540,60,"2007",3,0,2,2,0,11,0,1,2,0),
array("Arab","Asia/Riyadh",180,0,"",0,0,0,0,0,0,0,0,0,0),
array("Arabian","Asia/Dubai",240,0,"",0,0,0,0,0,0,0,0,0,0),
array("Arabic","Asia/Baghdad",180,60,"",4,0,1,3,0,10,0,1,4,0),
array("AST/ADT","America/Halifax",-240,60,"",3,0,2,2,0,11,0,1,2,0),
array("AST/ADT","America/Halifax",-240,60,"2006",4,0,1,2,0,10,0,5,2,0),
array("AST/ADT","America/Halifax",-240,60,"2007",3,0,2,2,0,11,0,1,2,0),
array("HNA/HAA","America/Halifax",-240,60,"",3,0,2,2,0,11,0,1,2,0),
array("HNA/HAA","America/Halifax",-240,60,"2006",4,0,1,2,0,10,0,5,2,0),
array("HNA/HAA","America/Halifax",-240,60,"2007",3,0,2,2,0,11,0,1,2,0),
array("Atlantic","America/Halifax",-240,60,"",3,0,2,2,0,11,0,1,2,0),
array("Atlantic","America/Halifax",-240,60,"2006",4,0,1,2,0,10,0,5,2,0),
array("Atlantic","America/Halifax",-240,60,"2007",3,0,2,2,0,11,0,1,2,0),
array("AUS_Central","Australia/Darwin",570,0,"",0,0,0,0,0,0,0,0,0,0),
array("AUS_Eastern","Australia/Sydney",600,60,"",10,0,5,2,0,3,0,5,3,0),
array("Azerbaijan","Asia/Baku",240,60,"",3,0,5,4,0,10,0,5,5,0),
array("Azores","Atlantic/Azores",-60,60,"",3,0,5,2,0,10,0,5,3,0),
array("Canada_Central","America/Regina",-360,0,"",0,0,0,0,0,0,0,0,0,0),
array("Cape_Verde","Atlantic/Cape_Verde",-60,0,"",0,0,0,0,0,0,0,0,0,0),
array("Caucasus","Asia/Tbilisi",240,60,"",3,0,5,2,0,10,0,5,3,0),
array("ACST/ACDT","Australia/Adelaide",570,60,"",10,0,5,2,0,3,0,5,3,0),
array("Central_Australia","Australia/Adelaide",570,60,"",10,0,5,2,0,3,0,5,3,0),
array("Central_America","America/Guatemala",-360,0,"",0,0,0,0,0,0,0,0,0,0),
array("Central_Asia","Asia/Dhaka",360,0,"",0,0,0,0,0,0,0,0,0,0),
array("Central_Brazilian","America/Manaus",-240,60,"",11,0,1,0,0,2,0,5,0,0),
array("Central_Brazilian","America/Manaus",-240,60,"2006",11,0,1,0,0,2,0,2,2,0),
array("Central_Brazilian","America/Manaus",-240,60,"2007",11,0,1,0,0,2,0,5,0,0),
array("CET/CEST","Europe/Zurich",60,60,"",3,0,5,2,0,10,0,5,3,0),
array("MEZ/MESZ","Europe/Berlin",60,60,"",3,0,5,2,0,10,0,5,3,0),
array("Central_Europe","Europe/Budapest",60,60,"",3,0,5,2,0,10,0,5,3,0),
array("Central_European","Europe/Warsaw",60,60,"",3,0,5,2,0,10,0,5,3,0),
array("Central_Pacific","Pacific/Guadalcanal",660,0,"",0,0,0,0,0,0,0,0,0,0),
array("CST/CDT","America/Chicago",-360,60,"",3,0,2,2,0,11,0,1,2,0),
array("CST/CDT","America/Chicago",-360,60,"2006",4,0,1,2,0,10,0,5,2,0),
array("CST/CDT","America/Chicago",-360,60,"2007",3,0,2,2,0,11,0,1,2,0),
array("HNC/HAC","America/Chicago",-360,60,"",3,0,2,2,0,11,0,1,2,0),
array("HNC/HAC","America/Chicago",-360,60,"2006",4,0,1,2,0,10,0,5,2,0),
array("HNC/HAC","America/Chicago",-360,60,"2007",3,0,2,2,0,11,0,1,2,0),
array("Central","America/Chicago",-360,60,"",3,0,2,2,0,11,0,1,2,0),
array("Central","America/Chicago",-360,60,"2006",4,0,1,2,0,10,0,5,2,0),
array("Central","America/Chicago",-360,60,"2007",3,0,2,2,0,11,0,1,2,0),
array("Central_Mexico","America/Mexico_City",-360,60,"",4,0,1,2,0,10,0,5,2,0),
array("China","Asia/Shanghai",480,0,"",0,0,0,0,0,0,0,0,0,0),
array("Dateline","Etc/GMT+12",-720,0,"",0,0,0,0,0,0,0,0,0,0),
array("East_Africa","Africa/Nairobi",180,0,"",0,0,0,0,0,0,0,0,0,0),
array("AEST/AEDT","Australia/Brisbane",600,0,"",0,0,0,0,0,0,0,0,0,0),
array("East_Australia","Australia/Brisbane",600,0,"",0,0,0,0,0,0,0,0,0,0),
array("EET/EEST","Europe/Minsk",120,60,"",3,0,5,2,0,10,0,5,3,0),
array("East_Europe","Europe/Minsk",120,60,"",3,0,5,2,0,10,0,5,3,0),
array("East_South_America","America/Sao_Paulo",-180,60,"",11,0,1,0,0,2,0,5,0,0),
array("East_South_America","America/Sao_Paulo",-180,60,"2006",11,0,1,0,0,2,0,2,2,0),
array("East_South_America","America/Sao_Paulo",-180,60,"2007",11,0,1,0,0,2,0,5,0,0),
array("EST/EDT","America/New_York",-300,60,"",3,0,2,2,0,11,0,1,2,0),
array("EST/EDT","America/New_York",-300,60,"2006",4,0,1,2,0,10,0,5,2,0),
array("EST/EDT","America/New_York",-300,60,"2007",3,0,2,2,0,11,0,1,2,0),
array("HNE/HAE","America/New_York",-300,60,"",3,0,2,2,0,11,0,1,2,0),
array("HNE/HAE","America/New_York",-300,60,"2006",4,0,1,2,0,10,0,5,2,0),
array("HNE/HAE","America/New_York",-300,60,"2007",3,0,2,2,0,11,0,1,2,0),
array("Eastern","America/New_York",-300,60,"",3,0,2,2,0,11,0,1,2,0),
array("Eastern","America/New_York",-300,60,"2006",4,0,1,2,0,10,0,5,2,0),
array("Eastern","America/New_York",-300,60,"2007",3,0,2,2,0,11,0,1,2,0),
array("Egypt","Africa/Cairo",120,60,"",4,4,5,23,59,9,4,5,23,59),
array("Ekaterinburg","Asia/Yekaterinburg",300,60,"",3,0,5,2,0,10,0,5,3,0),
array("Fiji","Pacific/Fiji",720,0,"",0,0,0,0,0,0,0,0,0,0),
array("FLE","Europe/Kiev",120,60,"",3,0,5,3,0,10,0,5,4,0),
array("Georgian","Etc/GMT-3",180,0,"",0,0,0,0,0,0,0,0,0,0),
array("GMT","Europe/London",0,60,"",3,0,5,1,0,10,0,5,2,0),
array("Greenland","America/Godthab",-180,60,"",4,0,1,2,0,10,0,5,2,0),
array("Greenwich","Africa/Casablanca",0,0,"",0,0,0,0,0,0,0,0,0,0),
array("GTB","Europe/Istanbul",120,60,"",3,0,5,3,0,10,0,5,4,0),
array("HAST/HADT","Pacific/Honolulu",-600,0,"",0,0,0,0,0,0,0,0,0,0),
array("Hawaiian","Pacific/Honolulu",-600,0,"",0,0,0,0,0,0,0,0,0,0),
array("India","Asia/Calcutta",330,0,"",0,0,0,0,0,0,0,0,0,0),
array("Iran","Asia/Tehran",210,0,"",0,0,0,0,0,0,0,0,0,0),
array("Iran","Asia/Tehran",210,60,"2005",3,0,1,2,0,9,2,4,2,0),
array("Iran","Asia/Tehran",210,0,"2006",0,0,0,0,0,0,0,0,0,0),
array("Israel","Asia/Jerusalem",120,60,"",3,5,5,2,0,9,0,3,2,0),
array("Israel","Asia/Jerusalem",120,0,"2004",0,0,0,0,0,0,0,0,0,0),
array("Israel","Asia/Jerusalem",120,60,"2005",4,-1,1,2,0,10,-1,9,2,0),
array("Israel","Asia/Jerusalem",120,60,"2006",3,-1,31,2,0,10,-1,1,2,0),
array("Israel","Asia/Jerusalem",120,60,"2007",3,-1,30,2,0,9,-1,16,2,0),
array("Israel","Asia/Jerusalem",120,60,"2008",3,-1,28,2,0,10,-1,5,2,0),
array("Israel","Asia/Jerusalem",120,60,"2009",3,-1,27,2,0,9,-1,27,2,0),
array("Israel","Asia/Jerusalem",120,60,"2010",3,-1,26,2,0,9,-1,12,2,0),
array("Israel","Asia/Jerusalem",120,60,"2011",4,-1,1,2,0,10,-1,2,2,0),
array("Israel","Asia/Jerusalem",120,60,"2012",3,-1,30,2,0,9,-1,23,2,0),
array("Israel","Asia/Jerusalem",120,60,"2013",3,-1,29,2,0,9,-1,8,2,0),
array("Israel","Asia/Jerusalem",120,60,"2014",3,-1,28,2,0,9,-1,28,2,0),
array("Israel","Asia/Jerusalem",120,60,"2015",3,-1,27,2,0,9,-1,20,2,0),
array("Israel","Asia/Jerusalem",120,60,"2016",4,-1,1,2,0,10,-1,9,2,0),
array("Israel","Asia/Jerusalem",120,60,"2017",3,-1,31,2,0,9,-1,24,2,0),
array("Israel","Asia/Jerusalem",120,60,"2018",3,-1,30,2,0,9,-1,16,2,0),
array("Israel","Asia/Jerusalem",120,60,"2019",3,-1,29,2,0,10,-1,6,2,0),
array("Israel","Asia/Jerusalem",120,60,"2020",3,-1,27,2,0,9,-1,27,2,0),
array("Israel","Asia/Jerusalem",120,60,"2021",3,-1,26,2,0,9,-1,12,2,0),
array("Israel","Asia/Jerusalem",120,60,"2022",4,-1,1,2,0,10,-1,2,2,0),
array("Israel","Asia/Jerusalem",120,0,"2023",0,0,0,0,0,0,0,0,0,0),
array("Jordan","Asia/Amman",120,60,"",3,4,5,0,0,9,5,5,1,0),
array("Korea","Asia/Seoul",540,0,"",0,0,0,0,0,0,0,0,0,0),
array("Mexico","America/Mexico_City",-360,60,"",4,0,1,2,0,10,0,5,2,0),
array("Mexico_2","America/Chihuahua",-420,60,"",4,0,1,2,0,10,0,5,2,0),
array("Mid_Atlantic","Atlantic/South_Georgia",-120,60,"",3,0,5,2,0,9,0,5,2,0),
array("Middle_East","Asia/Beirut",120,60,"",3,0,5,0,0,10,6,5,23,59),
array("Montevideo","America/Montevideo",-180,60,"",10,0,1,2,0,3,0,2,2,0),
array("MST/MDT","America/Denver",-420,60,"",3,0,2,2,0,11,0,1,2,0),
array("MST/MDT","America/Denver",-420,60,"2006",4,0,1,2,0,10,0,5,2,0),
array("MST/MDT","America/Denver",-420,60,"2007",3,0,2,2,0,11,0,1,2,0),
array("HNR/HAR","America/Denver",-420,60,"",3,0,2,2,0,11,0,1,2,0),
array("HNR/HAR","America/Denver",-420,60,"2006",4,0,1,2,0,10,0,5,2,0),
array("HNR/HAR","America/Denver",-420,60,"2007",3,0,2,2,0,11,0,1,2,0),
array("Mountain","America/Denver",-420,60,"",3,0,2,2,0,11,0,1,2,0),
array("Mountain","America/Denver",-420,60,"2006",4,0,1,2,0,10,0,5,2,0),
array("Mountain","America/Denver",-420,60,"2007",3,0,2,2,0,11,0,1,2,0),
array("Mountain_Mexico","America/Chihuahua",-420,60,"",4,0,1,2,0,10,0,5,2,0),
array("Myanmar","Asia/Rangoon",390,0,"",0,0,0,0,0,0,0,0,0,0),
array("North_Central_Asia","Asia/Novosibirsk",360,60,"",3,0,5,2,0,10,0,5,3,0),
array("Namibia","Africa/Windhoek",120,-60,"",4,0,1,2,0,9,0,1,2,0),
array("Nepal","Asia/Katmandu",345,0,"",0,0,0,0,0,0,0,0,0,0),
array("New_Zealand","Pacific/Auckland",720,60,"",10,0,1,2,0,3,0,3,3,0),
array("NST/NDT","America/St_Johns",-210,60,"",3,0,2,0,1,11,0,1,0,1),
array("NST/NDT","America/St_Johns",-210,60,"2006",4,0,1,0,1,10,0,5,0,0),
array("NST/NDT","America/St_Johns",-210,60,"2007",3,0,2,0,1,11,0,1,0,0),
array("HNT/HAT","America/St_Johns",-210,60,"",3,0,2,0,1,11,0,1,0,1),
array("HNT/HAT","America/St_Johns",-210,60,"2006",4,0,1,0,1,10,0,5,0,0),
array("HNT/HAT","America/St_Johns",-210,60,"2007",3,0,2,0,1,11,0,1,0,0),
array("Newfoundland","America/St_Johns",-210,60,"",3,0,2,0,1,11,0,1,0,1),
array("Newfoundland","America/St_Johns",-210,60,"2006",4,0,1,0,1,10,0,5,0,0),
array("Newfoundland","America/St_Johns",-210,60,"2007",3,0,2,0,1,11,0,1,0,0),
array("North_Asia_East","Asia/Irkutsk",480,60,"",3,0,5,2,0,10,0,5,3,0),
array("North_Asia","Asia/Krasnoyarsk",420,60,"",3,0,5,2,0,10,0,5,3,0),
array("Pacific_SA","America/Santiago",-240,60,"",10,6,2,23,59,3,6,2,23,59),
array("PST/PDT","America/Los_Angeles",-480,60,"",3,0,2,2,0,11,0,1,2,0),
array("PST/PDT","America/Los_Angeles",-480,60,"2006",4,0,1,2,0,10,0,5,2,0),
array("PST/PDT","America/Los_Angeles",-480,60,"2007",3,0,2,2,0,11,0,1,2,0),
array("HNP/HAP","America/Los_Angeles",-480,60,"",3,0,2,2,0,11,0,1,2,0),
array("HNP/HAP","America/Los_Angeles",-480,60,"2006",4,0,1,2,0,10,0,5,2,0),
array("HNP/HAP","America/Los_Angeles",-480,60,"2007",3,0,2,2,0,11,0,1,2,0),
array("Pacific","America/Los_Angeles",-480,60,"",3,0,2,2,0,11,0,1,2,0),
array("Pacific","America/Los_Angeles",-480,60,"2006",4,0,1,2,0,10,0,5,2,0),
array("Pacific","America/Los_Angeles",-480,60,"2007",3,0,2,2,0,11,0,1,2,0),
array("Pacific_Mexico","America/Tijuana",-480,60,"",4,0,1,2,0,10,0,5,2,0),
array("Romance","Europe/Paris",60,60,"",3,0,5,2,0,10,0,5,3,0),
array("Russian","Europe/Moscow",180,60,"",3,0,5,2,0,10,0,5,3,0),
array("SA_Eastern","Etc/GMT+3",-180,0,"",0,0,0,0,0,0,0,0,0,0),
array("SA_Pacific","America/Bogota",-300,0,"",0,0,0,0,0,0,0,0,0,0),
array("SA_Western","America/La_Paz",-240,0,"",0,0,0,0,0,0,0,0,0,0),
array("Samoa","Pacific/Apia",-660,0,"",0,0,0,0,0,0,0,0,0,0),
array("SE_Asia","Asia/Bangkok",420,0,"",0,0,0,0,0,0,0,0,0,0),
array("Singapore","Asia/Singapore",480,0,"",0,0,0,0,0,0,0,0,0,0),
array("South_Africa","Africa/Johannesburg",120,0,"",0,0,0,0,0,0,0,0,0,0),
array("Sri_Lanka","Asia/Colombo",330,0,"",0,0,0,0,0,0,0,0,0,0),
array("Taipei","Asia/Taipei",480,0,"",0,0,0,0,0,0,0,0,0,0),
array("Tasmania","Australia/Hobart",600,60,"",10,0,1,2,0,3,0,5,3,0),
array("Tokyo","Asia/Tokyo",540,0,"",0,0,0,0,0,0,0,0,0,0),
array("Tonga","Pacific/Tongatapu",780,0,"",0,0,0,0,0,0,0,0,0,0),
array("US_Eastern","Etc/GMT+5",-300,0,"",0,0,0,0,0,0,0,0,0,0),
array("US_Mountain","America/Phoenix",-420,0,"",0,0,0,0,0,0,0,0,0,0),
array("Vladivostok","Asia/Vladivostok",600,60,"",3,0,5,2,0,10,0,5,3,0),
array("West_Australia","Australia/Perth",480,60,"",10,0,5,2,0,3,0,5,3,0),
array("West_Australia","Australia/Perth",480,0,"2005",0,0,0,0,0,0,0,0,0,0),
array("West_Australia","Australia/Perth",480,60,"2006",12,-1,1,2,0,1,-1,1,0,0),
array("West_Australia","Australia/Perth",480,60,"2007",10,0,5,2,0,3,0,5,3,0),
array("West_Central_Africa","Africa/Lagos",60,0,"",0,0,0,0,0,0,0,0,0,0),
array("WET/WEST","Europe/Berlin",60,60,"",3,0,5,2,0,10,0,5,3,0),
array("West_Europe","Europe/Berlin",60,60,"",3,0,5,2,0,10,0,5,3,0),
array("West_Asia","Asia/Karachi",300,0,"",0,0,0,0,0,0,0,0,0,0),
array("West_Pacific","Pacific/Port_Moresby",600,0,"",0,0,0,0,0,0,0,0,0,0),
array("Yakutsk","Asia/Yakutsk",540,60,"",3,0,5,2,0,10,0,5,3,0),
);
$serverTZ = date('e', $ts);
$year = date('Y', $ts);
$i = 0;
$row =& $utc;
do
{
$tbl_tz_row =& $tbl_tz[$i];
if ($row[0] != 'UTC' && $row[0] != $tbl_tz_row[0]) break;
if ($tbl_tz_row[1] == $serverTZ
&& ($tbl_tz_row[4] != "" || $year >= (int) $tbl_tz_row[4]))
{
$row =& $tbl_tz[$i];
}
$i++;
}
while (is_array($tbl_tz[$i]));
if (preg_match('/(.+)\/(.+)/', $row[0], $matches))
{
$stdname = $matches[1];
$dstname = $matches[2];
}
else
{
$stdname = $dstname = $row[0];
}
$container = false;
$vtimezone = Horde_iCalendar::newComponent('VTIMEZONE', $container);
$vtimezone->setAttribute('TZID', $row[1]);
$minutes = $row[2] + $row[3];
$value1['ahead'] = ($minutes > 0);
$minutes = abs($minutes);
$value1['hour'] = (int)$minutes / 60;
$value1['minute'] = $minutes % 60;
$minutes = $row[2];
$value2['ahead'] = ($minutes > 0);
$minutes = abs($minutes);
$value2['hour'] = (int)$minutes / 60;
$value2['minute'] = $minutes % 60;
$daylight = Horde_iCalendar::newComponent('DAYLIGHT', $container);
$dtstart = $this->calc_dtstart($row[4], $row[5], $row[6], $row[7], $row[8], $row[9]);
$daylight->setAttribute('DTSTART', $dtstart);
$byday = ($row[7] == 5 ? '-1' : $row[7]) . $dayofweek[$row[6]];
$daylight->setAttribute('RRULE', '', array('FREQ' => 'YEARLY', 'BYMONTH' => $row[5], 'BYDAY' => $byday));
$daylight->setAttribute('TZNAME', $dstname);
$daylight->setAttribute('TZOFFSETFROM', $value2);
$daylight->setAttribute('TZOFFSETTO', $value1);
$standard = Horde_iCalendar::newComponent('STANDARD', $container);
$dtstart = $this->calc_dtstart($year, $row[10], $row[11], $row[12], $row[13], $row[14]);
$standard->setAttribute('DTSTART', $dtstart);
$byday = ($row[12] == 5 ? '-1' : $row[12]) . $dayofweek[$row[11]];
$standard->setAttribute('RRULE', '', array('FREQ' => 'YEARLY', 'BYMONTH' => $row[10], 'BYDAY' => $byday));
$standard->setAttribute('TZNAME', $stdname);
$standard->setAttribute('TZOFFSETFROM', $value1);
$standard->setAttribute('TZOFFSETTO', $value2);
$vtimezone->addComponent($daylight);
$vtimezone->addComponent($standard);
$vevent->addComponent($vtimezone);
return $row[1];
}
/**
* calculate the DTSTART value for a given timezone switch occurrence
*
* @param int $wYear
* @param int $wMonth
* @param int $wDayOfWeek
* @param int $wNth n-th day of week (5 last occurrence)
* @param int $wHour
* @param int $wMinute
* @return string DTSTART entry
*/
function calc_dtstart($wYear, $wMonth, $wDayOfWeek, $wNth, $wHour, $wMinute)
{
if (!$wYear) $wYear = 1981;
if ($wNth < 5)
{
$ts = mktime($wHour, $wMinute, 0, $wMonth, 1, $wYear);
$day = $wDayOfWeek - date('w', $ts);
if ($day < 0) $day += 7;
$day += 7 * ($wNth - 1) + 1;
$ts = mktime($wHour, $wMinute, 0, $wMonth, $day, $wYear);
}
else
{
$ts = mktime($wHour, $wMinute, 0, $wMonth, 31, $wYear);
$day = $wDayOfWeek - date('w', $ts);
if ($day > 0) $day -= 7;
$day += 31;
do
{
$ts = mktime($wHour, $wMinute, 0, $wMonth, $day, $wYear);
$day -= 7;
} while ($wMonth < date('n', $ts));
}
$dtstart = date('Ymd\T', $ts) . sprintf("%'02u%'02u00", $wHour, $wMinute);
return $dtstart;
}
} }