Fixed DST issues but still working with timestamps because Kolab_Format does

This commit is contained in:
Thomas 2011-09-28 16:47:18 +02:00
parent 5c054b1094
commit 154d25b5b9
4 changed files with 42 additions and 16 deletions

View file

@ -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 . ')';
}

View file

@ -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,

View file

@ -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

View file

@ -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;