From 154d25b5b9a461295de48070aaa7970970c0dc94 Mon Sep 17 00:00:00 2001 From: Thomas Date: Wed, 28 Sep 2011 16:47:18 +0200 Subject: [PATCH] Fixed DST issues but still working with timestamps because Kolab_Format does --- plugins/calendar/calendar.php | 30 +++++++++++++++---- plugins/calendar/calendar_ui.js | 8 ++++- .../calendar/drivers/kolab/kolab_calendar.php | 8 ++--- plugins/calendar/lib/calendar_ical.php | 12 ++++---- 4 files changed, 42 insertions(+), 16 deletions(-) diff --git a/plugins/calendar/calendar.php b/plugins/calendar/calendar.php index a79db6ca..c86a9b56 100644 --- a/plugins/calendar/calendar.php +++ b/plugins/calendar/calendar.php @@ -96,8 +96,10 @@ class calendar extends rcube_plugin $this->add_texts('localization/', $this->rc->task == 'calendar' && (!$this->rc->action || $this->rc->action == 'print')); // set user's timezone - $this->timezone = $this->rc->config->get_timezone(); - $this->gmt_offset = $this->timezone * 3600; + $this->timezone = $this->rc->config->get('timezone'); + $this->dst_active = $this->rc->config->get('dst_active'); + $this->gmt_offset = ($this->timezone + $this->dst_active) * 3600; + $this->user_timezone = new DateTimeZone($this->timezone ? timezone_name_from_abbr("", $this->gmt_offset, $this->dst_active) : 'GMT'); require($this->home . '/lib/calendar_ui.php'); $this->ui = new calendar_ui($this); @@ -589,11 +591,13 @@ class calendar extends rcube_plugin break; case "resize": + $this->prepare_event($event, $action); $success = $this->driver->resize_event($event); $reload = $event['_savemode'] ? 2 : 1; break; case "move": + $this->prepare_event($event, $action); $success = $this->driver->move_event($event); $reload = $success && $event['_savemode'] ? 2 : 1; break; @@ -850,6 +854,7 @@ class calendar extends rcube_plugin $settings['agenda_sections'] = $this->rc->config->get('calendar_agenda_sections', $this->defaults['calendar_agenda_sections']); $settings['event_coloring'] = (int)$this->rc->config->get('calendar_event_coloring', $this->defaults['calendar_event_coloring']); $settings['timezone'] = $this->timezone; + $settings['dst'] = $this->dst_active; // localization $settings['days'] = array( @@ -934,6 +939,19 @@ class calendar extends rcube_plugin return $ts + $this->gmt_offset; } + /** + * Fix DST difference between client and target date + */ + function fixDST($time) + { + $date = new DateTime(null, $this->user_timezone); + $date->setTimeStamp($time); + $diff = $date->format('I') - $this->dst_active; + $time += $diff * 3600; + + return $time; + } + /** * Encode events as JSON * @@ -1447,9 +1465,11 @@ class calendar extends rcube_plugin */ private function prepare_event(&$event, $action) { - $eventid = 'cal:'.$event['id']; + $event['start'] = $this->fixDST($event['start']); + $event['end'] = $this->fixDST($event['end']); $attachments = array(); + $eventid = 'cal:'.$event['id']; if (is_array($_SESSION['event_session']) && $_SESSION['event_session']['id'] == $eventid) { if (!empty($_SESSION['event_session']['attachments'])) { foreach ($_SESSION['event_session']['attachments'] as $id => $attachment) { @@ -1463,7 +1483,7 @@ class calendar extends rcube_plugin $event['attachments'] = $attachments; // check for organizer in attendees - if ($event['attendees']) { + if ($event['attendees'] && ($action == 'new' || $action == 'edit')) { $emails = $this->get_user_emails(); $organizer = $owner = false; foreach ($event['attendees'] as $i => $attendee) { @@ -1571,7 +1591,7 @@ class calendar extends rcube_plugin } // add timezone information - if ($tzinfo && ($tzname = timezone_name_from_abbr("", $this->gmt_offset, 0))) { + if ($tzinfo && ($tzname = $this->user_timezone->getName())) { $fromto .= ' (' . $tzname . ')'; } diff --git a/plugins/calendar/calendar_ui.js b/plugins/calendar/calendar_ui.js index 817d3317..6f054017 100644 --- a/plugins/calendar/calendar_ui.js +++ b/plugins/calendar/calendar_ui.js @@ -32,7 +32,7 @@ function rcube_calendar_ui(settings) var DAY_MS = 86400000; var HOUR_MS = 3600000; var me = this; - var gmt_offset = (new Date().getTimezoneOffset() / -60) - (settings.timezone || 0); + var gmt_offset = (new Date().getTimezoneOffset() / -60) - (settings.timezone || 0) - (settings.dst || 0); var day_clicked = day_clicked_ts = 0; var ignore_click = false; var event_defaults = { free_busy:'busy' }; @@ -2272,6 +2272,12 @@ function rcube_calendar_ui(settings) }, // callback for event resizing eventResize: function(event, delta) { + // sanitize event dates + if (event.allDay) + event.start.setHours(12); + if (!event.end || event.end.getTime() < event.start.getTime()) + event.end = new Date(event.start.getTime() + HOUR_MS); + // send resize request to server var data = { id: event.id, diff --git a/plugins/calendar/drivers/kolab/kolab_calendar.php b/plugins/calendar/drivers/kolab/kolab_calendar.php index 9ee32531..390fd14a 100644 --- a/plugins/calendar/drivers/kolab/kolab_calendar.php +++ b/plugins/calendar/drivers/kolab/kolab_calendar.php @@ -447,7 +447,7 @@ class kolab_calendar $events = array(); $duration = $event['end'] - $event['start']; - $tz_offset = $event['allday'] ? $this->cal->timezone * 3600 - date('Z') : 0; + $tz_offset = $event['allday'] ? $this->cal->gmt_offset - date('Z') : 0; $next = new Horde_Date($event['start'] + $tz_offset); # shift all-day times to server timezone because computation operates in local TZ $dst_start = $next->format('I'); $hour = $next->hour; @@ -494,8 +494,8 @@ class kolab_calendar if ($allday) { // in Roundcube all-day events only go from 12:00 to 13:00 $rec['start-date'] += 12 * 3600; $rec['end-date'] -= 11 * 3600; - $rec['end-date'] -= $this->cal->timezone * 3600 - date('Z', $rec['end-date']); // shift 00 times from server's timezone to user's timezone - $rec['start-date'] -= $this->cal->timezone * 3600 - date('Z', $rec['start-date']); // because generated with mktime() in Horde_Kolab_Format_Date::decodeDate() + $rec['end-date'] -= $this->cal->gmt_offset - date('Z', $rec['end-date']); // shift times from server's timezone to user's timezone + $rec['start-date'] -= $this->cal->gmt_offset - date('Z', $rec['start-date']); // because generated with mktime() in Horde_Kolab_Format_Date::decodeDate() // sanity check if ($rec['end-date'] <= $rec['start-date']) $rec['end-date'] += 86400; @@ -623,7 +623,7 @@ class kolab_calendar private function _from_rcube_event($event) { $priority_map = $this->priority_map; - $tz_offset = $this->cal->timezone * 3600; + $tz_offset = $this->cal->gmt_offset; $object = array( // kolab => roundcube diff --git a/plugins/calendar/lib/calendar_ical.php b/plugins/calendar/lib/calendar_ical.php index 497c39d8..ca6c6d43 100644 --- a/plugins/calendar/lib/calendar_ical.php +++ b/plugins/calendar/lib/calendar_ical.php @@ -52,7 +52,7 @@ class calendar_ical // compose timezone string if ($cal->timezone) { - $hours = floor($cal->timezone); + $hours = floor($cal->timezone + $cal->dst_active); $this->timezone = sprintf('%s%02d:%02d', ($hours >= 0 ? '+' : ''), $hours, ($cal->timezone - $hours) * 60); } } @@ -104,12 +104,12 @@ class calendar_ical // check for all-day dates if (is_array($event['start'])) { - // create timestamp at 00:00 in user's timezone + // create timestamp at 12:00 in user's timezone $event['start'] = $this->_date2time($event['start']); $event['allday'] = true; } if (is_array($event['end'])) { - $event['end'] = $this->_date2time($event['end']) - 60; + $event['end'] = $this->_date2time($event['end']) - 23 * 3600; } // map other attributes to internal fields @@ -221,8 +221,8 @@ class calendar_ical */ private function _date2time($prop) { - // create timestamp at 00:00 in user's timezone - return is_array($prop) ? strtotime(sprintf('%04d%02d%02dT000000%s', $prop['year'], $prop['month'], $prop['mday'], $this->timezone)) : $prop; + // create timestamp at 12:00 in user's timezone + return is_array($prop) ? strtotime(sprintf('%04d%02d%02dT120000%s', $prop['year'], $prop['month'], $prop['mday'], $this->timezone)) : $prop; } @@ -265,7 +265,7 @@ class calendar_ical // correctly set all-day dates if ($event['allday']) { $vevent .= "DTSTART;VALUE=DATE:" . gmdate('Ymd', $event['start'] + $this->cal->gmt_offset) . self::EOL; - $vevent .= "DTEND;VALUE=DATE:" . gmdate('Ymd', $event['end'] + $this->cal->gmt_offset + 60) . self::EOL; // ends the next day + $vevent .= "DTEND;VALUE=DATE:" . gmdate('Ymd', $event['end'] + $this->cal->gmt_offset + 86400) . self::EOL; // ends the next day } else { $vevent .= "DTSTART:" . gmdate('Ymd\THis\Z', $event['start']) . self::EOL;