From 52ba3b8146dd01c1c7d057359f4485aae5813124 Mon Sep 17 00:00:00 2001 From: Jim Hu Date: Thu, 25 Dec 2008 18:45:26 +0000 Subject: progress on timezones and daylight time --- functions/date_functions.php | 143 +++--- functions/is_daylight.php | 292 +++++++++++ functions/parse/end_vevent.php | 86 ++-- functions/parse/recur_functions.php | 3 +- functions/timezones.php | 976 ++++++++++++++++++------------------ 5 files changed, 908 insertions(+), 592 deletions(-) create mode 100644 functions/is_daylight.php (limited to 'functions') diff --git a/functions/date_functions.php b/functions/date_functions.php index 3ba1b94..07745c1 100644 --- a/functions/date_functions.php +++ b/functions/date_functions.php @@ -153,7 +153,7 @@ function chooseOffset($time, $timezone = '') { break; default: if (is_array($tz_array) && array_key_exists($timezone, $tz_array)) { - $dlst = date('I', $time); + $dlst = is_daylight($time, $timezone); $offset = $tz_array[$timezone][$dlst]; } else { $offset = '+0000'; @@ -208,76 +208,105 @@ $return = " return $return; } -// Returns an array of the date and time extracted from the data -// passed in. This array contains (unixtime, date, time, allday). -// -// $data = A string representing a date-time per RFC2445. -// $property = The property being examined, e.g. DTSTART, DTEND. -// $field = The full field being examined, e.g. DTSTART;TZID=US/Pacific -function extractDateTime($data, $property, $field) { - global $tz_array, $phpiCal_config; - - // Initialize values. - unset($unixtime, $date, $time, $allday); +/* Returns an array of the date and time extracted from the data + passed in. This array contains (unixtime, date, time, allday). + + $data = A string representing a date-time per RFC2445. + $property = The property being examined, e.g. DTSTART, DTEND. + $field = The full field being examined, e.g. DTSTART;TZID=US/Pacific +See:http://phpicalendar.org/documentation/index.php/Property_Value_Data_Types#4.3.5___Date-Time +*/ +function extractDateTime($data, $property, $field) { + global $tz_array, $phpiCal_config, $calendar_tz; + $allday =''; #suppress error on returning undef. // Check for zulu time. $zulu_time = false; if (substr($data,-1) == 'Z') $zulu_time = true; - $data = str_replace('Z', '', $data); - - // Remove some substrings we don't want to look at. - $data = str_replace('T', '', $data); - $field = str_replace(';VALUE=DATE-TIME', '', $field); + // Pull out the timezone, or use GMT if zulu time was indicated. + if (preg_match('/^'.$property.';TZID=/i', $field)) { + $tz_tmp = explode('=', $field); + $tz_dt = match_tz($tz_tmp[1]); #echo "$tz_dt
"; + } elseif ($zulu_time) { + $tz_dt = 'GMT'; + } // Extract date-only values. - if ((preg_match('/^'.$property.';VALUE=DATE/i', $field)) || (ereg ('^([0-9]{4})([0-9]{2})([0-9]{2})$', $data))) { + if ((preg_match('/^'.$property.';VALUE=DATE:/i', $field)) || (ereg ('^([0-9]{4})([0-9]{2})([0-9]{2})$', $data))) { // Pull out the date value. Minimum year is 1970. ereg ('([0-9]{4})([0-9]{2})([0-9]{2})', $data, $dt_check); if ($dt_check[1] < 1970) { $data = '1971'.$dt_check[2].$dt_check[3]; - } - - // Set the values. - $unixtime = strtotime($data); - $date = date('Ymd', $unixtime); + } + # convert to date-time + $data = $dt_check[1].$dt_check[2].$dt_check[3]."T000000"; $time = ''; $allday = $data; - }else{ // Extract date-time values. - - // Pull out the timezone, or use GMT if zulu time was indicated. - if (preg_match('/^'.$property.';TZID=/i', $field)) { - $tz_tmp = explode('=', $field); - $tz_dt = $tz_tmp[1]; - unset($tz_tmp); - } elseif ($zulu_time) { - $tz_dt = 'GMT'; - } - - // Pull out the date and time values. Minimum year is 1970. - preg_match ('/([0-9]{4})([0-9]{2})([0-9]{2})([0-9]{0,2})([0-9]{0,2})/', $data, $regs); - if ($regs[1] < 1970) { - $regs[1] = '1971'; - } - $date = $regs[1] . $regs[2] . $regs[3]; - $time = $regs[4] . $regs[5]; - $unixtime = mktime($regs[4], $regs[5], 0, $regs[2], $regs[3], $regs[1]); - // Check for daylight savings time. - $dlst = date('I', $unixtime); - $server_offset_tmp = chooseOffset($unixtime, $phpiCal_config->timezone); - if (isset($tz_dt)) { - $offset_tmp = chooseOffset($unixtime, $tz_dt); - } elseif (isset($calendar_tz)) { - $offset_tmp = chooseOffset($unixtime, $calendar_tz); - } else { - $offset_tmp = $server_offset_tmp; - } - // Set the values. - $unixtime = calcTime($offset_tmp, $server_offset_tmp, $unixtime); - $date = date('Ymd', $unixtime); - $time = date('Hi', $unixtime); - } + } + // Extract date-time values. + // Pull out the date and time values. Minimum year is 1970. + preg_match ('/([0-9]{4})([0-9]{2})([0-9]{2})T{0,1}([0-9]{0,2})([0-9]{0,2})/', $data, $regs); + if ($regs[1] < 1970) { + $regs[1] = '1971'; + } + $date = $regs[1] . $regs[2] . $regs[3]; + $time = $regs[4] . $regs[5]; + $unixtime = mktime($regs[4], $regs[5], 0, $regs[2], $regs[3], $regs[1]); + # chooseOffset checks for Daylight Saving Time + $server_offset_tmp = chooseOffset($unixtime, $phpiCal_config->timezone); + if (isset($tz_dt)) { + $offset_tmp = chooseOffset($unixtime, $tz_dt); + } elseif (isset($calendar_tz)) { + $offset_tmp = chooseOffset($unixtime, $calendar_tz); + } else { + $offset_tmp = $server_offset_tmp; + } + // Set the values. + $unixtime = calcTime($offset_tmp, $server_offset_tmp, $unixtime); + #echo "offset_tmp $offset_tmp, server_offset_tmp $server_offset_tmp, $unixtime =".date("Ymd His",$unixtime)." $time
"; + $date = date('Ymd', $unixtime); + if ($allday == '') $time = date('Hi', $unixtime); + // Return the results. return array($unixtime, $date, $time, $allday); } + +/* TZIDs in calendars often contain leading information that should be stripped +Example: TZID=/mozilla.org/20050126_1/Europe/Berlin +if this has been set by the parse_tzs scanning the file, then it should be OK, but sometimes a calendar may have a tzid without having defined the vtimezone, expecting a match (This will often happen when users send isolated events in bug reports; the calendars should have vtimezones). + +Need to return the part that matches a key in $tz_array +*/ +function match_tz($data){ + global $tz_array; + if (isset($tz_array[$data])) return $data; + foreach ($tz_array as $key=>$val){ + if (strpos(" $data",$key) > 0) return $key; + } + return $data; +} + +require_once(BASE."functions/is_daylight.php"); +/* function is_daylight($date, $timezone) returns 1 if daylight time, 0 if not + + default is to use the server's date function. This will be off when the timezone's rules are not the same as the server's rules. In php5.2+ there seems to be a better way to do this, but we can't count on users having php5.2+. + + Although we set dt_start and st_start in parse_tzs.php, these are not rrules and I don't know how to use them yet. So we'll do it by brute force for the ones we know about, from: http://www.webexhibits.org/daylightsaving/g.html + + Note that this sends a screwy time value - it's not necessarily UTC unixtime, since the mktime functions that create the time are not using the timezone. + +function is_daylight($time, $timezone){ + global $tz_array; + # default to std time, overwrite if daylight. + $dlst = 0; + switch ($timezone){ + default: + $dlst = date('I', $time); + } + + return $dlst; + +} +*/ ?> \ No newline at end of file diff --git a/functions/is_daylight.php b/functions/is_daylight.php new file mode 100644 index 0000000..c6f79ef --- /dev/null +++ b/functions/is_daylight.php @@ -0,0 +1,292 @@ += $start && $time < $end) $dlst = 1; + echo "$summary $dlst
"; + + return $dlst; + +} +?> \ No newline at end of file diff --git a/functions/parse/end_vevent.php b/functions/parse/end_vevent.php index 1dfe221..5970e65 100644 --- a/functions/parse/end_vevent.php +++ b/functions/parse/end_vevent.php @@ -320,7 +320,6 @@ foreach($recur_data as $recur_data_unixtime) { } else { $start_unixtime_tmp = mktime($recur_data_hour,$recur_data_minute,0,$recur_data_month,$recur_data_day,$recur_data_year); $end_unixtime_tmp = $start_unixtime_tmp + $length; - if (($end_time >= $phpiCal_config->bleed_time) && ($bleed_check == '-1')) { $start_tmp = strtotime(date('Ymd',$start_unixtime_tmp)); $end_date_tmp = date('Ymd',$end_unixtime_tmp); @@ -339,57 +338,18 @@ foreach($recur_data as $recur_data_unixtime) { $end_time_tmp = '2400'; $display_end_tmp = $end_time; } - - // Let's double check the until to not write past it - $until_check = $start_date_tmp.$time_tmp.'00'; - if (@$until > $until_check) { - $master_array[$start_date_tmp][$time_tmp][$uid] = array ( - 'event_start' => $start_time_tmp, - 'event_end' => $end_time_tmp, - 'start_unixtime' => $start_unixtime_tmp, - 'end_unixtime' => $end_unixtime_tmp, - 'event_text' => $summary, - 'event_length' => $length, - 'event_overlap' => 0, - 'description' => $description, - 'status' => $status, - 'class' => $class, - 'spans_day' => true, - 'location' => $location, - 'organizer' => serialize($organizer), - 'attendee' => serialize($attendee), - 'calnumber' => $calnumber, - 'calname' => $actual_calname, - 'url' => $url, - 'recur' => $recur); - if (isset($display_end_tmp)){ - $master_array[$start_date_tmp][$time_tmp][$uid]['display_end'] = $display_end_tmp; - } - checkOverlap($start_date_tmp, $time_tmp, $uid); - } - $start_tmp = strtotime('+1 day',$start_tmp); - } - } else { - if ($bleed_check == '-1') { - $display_end_tmp = $end_time; - $end_time_tmp1 = '2400'; - - } - if (!isset($end_time_tmp1)) $end_time_tmp1 = $end_time; - - // Let's double check the until to not write past it - $master_array[($recur_data_date)][($hour.$minute)][$uid] = array ( - 'event_start' => $start_time, - 'event_end' => $end_time_tmp1, + $master_array[$start_date_tmp][$time_tmp][$uid] = array ( + 'event_start' => $start_time_tmp, + 'event_end' => $end_time_tmp, 'start_unixtime' => $start_unixtime_tmp, 'end_unixtime' => $end_unixtime_tmp, - 'event_text' => $summary, + 'event_text' => $summary, # 'event_length' => $length, 'event_overlap' => 0, 'description' => $description, 'status' => $status, 'class' => $class, - 'spans_day' => false, + 'spans_day' => true, 'location' => $location, 'organizer' => serialize($organizer), 'attendee' => serialize($attendee), @@ -398,9 +358,41 @@ foreach($recur_data as $recur_data_unixtime) { 'url' => $url, 'recur' => $recur); if (isset($display_end_tmp)){ - $master_array[($recur_data_date)][($hour.$minute)][$uid]['display_end'] = $display_end_tmp; + $master_array[$start_date_tmp][$time_tmp][$uid]['display_end'] = $display_end_tmp; } - checkOverlap($recur_data_date, ($hour.$minute), $uid); + checkOverlap($start_date_tmp, $time_tmp, $uid); + $start_tmp = strtotime('+1 day',$start_tmp); + } + } else { + if ($bleed_check == '-1') { + $display_end_tmp = $end_time; + $end_time_tmp1 = '2400'; + + } + if (!isset($end_time_tmp1)) $end_time_tmp1 = $end_time; + $master_array[($recur_data_date)][($hour.$minute)][$uid] = array ( + 'event_start' => $start_time, + 'event_end' => $end_time_tmp1, + 'start_unixtime' => $start_unixtime_tmp, + 'end_unixtime' => $end_unixtime_tmp, + 'event_text' => $summary, + 'event_length' => $length, + 'event_overlap' => 0, + 'description' => $description, + 'status' => $status, + 'class' => $class, + 'spans_day' => false, + 'location' => $location, + 'organizer' => serialize($organizer), + 'attendee' => serialize($attendee), + 'calnumber' => $calnumber, + 'calname' => $actual_calname, + 'url' => $url, + 'recur' => $recur); + if (isset($display_end_tmp)){ + $master_array[($recur_data_date)][($hour.$minute)][$uid]['display_end'] = $display_end_tmp; + } + checkOverlap($recur_data_date, ($hour.$minute), $uid); } } diff --git a/functions/parse/recur_functions.php b/functions/parse/recur_functions.php index e45f4aa..6a58d2d 100644 --- a/functions/parse/recur_functions.php +++ b/functions/parse/recur_functions.php @@ -28,6 +28,7 @@ function add_recur($times,$freq=''){ if (!is_array($times)) $times = array($times); /*BYMONTH, BYWEEKNO, BYYEARDAY, BYMONTHDAY, BYDAY, BYHOUR, BYMINUTE, BYSECOND and BYSETPOS*/ +#dump_times($times); $times = restrict_bymonth($times,$freq); # $times = restrict_byweekno($times,$freq); $times = restrict_byyearday($times,$freq); @@ -253,6 +254,6 @@ function dump_times($times){ global $summary; echo "
$summary times:";
 	#var_dump($times);
-	foreach($times as $time) echo "\ndate:".date("Ymd his",$time);
+	foreach($times as $time) echo "\ndate:".date("Y-m-d H:i:s",$time);
 	echo "
"; } diff --git a/functions/timezones.php b/functions/timezones.php index 5c27a02..ae140f0 100644 --- a/functions/timezones.php +++ b/functions/timezones.php @@ -1,489 +1,491 @@ \ No newline at end of file -- cgit v1.2.3