diff --git a/SoObjects/Appointments/SOGoAppointmentFolder.m b/SoObjects/Appointments/SOGoAppointmentFolder.m index 4f2946731..d60f7a300 100644 --- a/SoObjects/Appointments/SOGoAppointmentFolder.m +++ b/SoObjects/Appointments/SOGoAppointmentFolder.m @@ -1,5 +1,5 @@ /* - Copyright (C) 2007-2012 Inverse inc. + Copyright (C) 2007-2013 Inverse inc. Copyright (C) 2004-2005 SKYRIX Software AG This file is part of SOGo. @@ -697,8 +697,10 @@ static NSNumber *sharedYes = nil; unsigned int count; NSCalendarDate *date; NSNumber *dateValue; + BOOL isAllDay; unsigned int offset; + isAllDay = [[theRecord objectForKey: @"c_isallday"] boolValue]; record = [[theRecord mutableCopy] autorelease]; for (count = 0; count < 2; count++) { @@ -709,7 +711,7 @@ static NSNumber *sharedYes = nil; if (date) { [date setTimeZone: timeZone]; - if ([[theRecord objectForKey: @"c_isallday"] boolValue]) + if (isAllDay) { // Since there's no timezone associated to all-day events, // their time must be adjusted for the user's timezone. @@ -788,6 +790,15 @@ static NSNumber *sharedYes = nil; [record setObject: date forKey: @"startDate"]; dateSecs = [NSNumber numberWithInt: [date timeIntervalSince1970]]; [record setObject: dateSecs forKey: @"c_startdate"]; + + if ([[record valueForKey: @"c_isallday"] boolValue]) + { + // Refer to all-day recurrence id by their GMT-based start date + date = [theCycle startDate]; + secondsOffsetFromGMT = (int) [[date timeZone] secondsFromGMTForDate: date]; + date = [date dateByAddingYears: 0 months: 0 days: 0 hours: 0 minutes: 0 seconds: secondsOffsetFromGMT]; + dateSecs = [NSNumber numberWithInt: [date timeIntervalSince1970]]; + } [record setObject: dateSecs forKey: @"c_recurrence_id"]; date = [theCycle endDate]; @@ -851,18 +862,18 @@ static NSNumber *sharedYes = nil; firstInstanceCalendarDateRange: (NGCalendarDateRange *) fir fromRow: (NSDictionary *) row forRange: (NGCalendarDateRange *) dateRange - withTimeZone: (NSTimeZone *) tz + withTimeZone: (NSTimeZone *) tz toArray: (NSMutableArray *) ma { - NSCalendarDate *startDate, *recurrenceId; + NSCalendarDate *recurrenceId; NSMutableDictionary *newRecord; NSDictionary *oldRecord; NGCalendarDateRange *newRecordRange; - NSComparisonResult compare; int recordIndex, secondsOffsetFromGMT; newRecord = nil; recurrenceId = [component recurrenceId]; + if (!recurrenceId) { [self errorWithFormat: @"ignored component with an empty EXCEPTION-ID"]; @@ -877,40 +888,32 @@ firstInstanceCalendarDateRange: (NGCalendarDateRange *) fir secondsOffsetFromGMT = [tz secondsFromGMTForDate: recurrenceId]; recurrenceId = (NSCalendarDate *) [recurrenceId dateByAddingYears:0 months:0 days:0 hours:0 minutes:0 seconds:-secondsOffsetFromGMT]; + [recurrenceId setTimeZone: tz]; } - compare = [[dateRange startDate] compare: recurrenceId]; - if ((compare == NSOrderedAscending || compare == NSOrderedSame) && - [[dateRange endDate] compare: recurrenceId] == NSOrderedDescending) + if ([dateRange containsDate: [component startDate]] || + [dateRange containsDate: [component endDate]]) { recordIndex = [self _indexOfRecordMatchingDate: recurrenceId inArray: ma]; if (recordIndex > -1) { - startDate = [component startDate]; - if ([dateRange containsDate: startDate]) - { - newRecord = [self fixupRecord: [component quickRecord]]; - [newRecord setObject: [NSNumber numberWithInt: 1] - forKey: @"c_iscycle"]; - oldRecord = [ma objectAtIndex: recordIndex]; - [newRecord setObject: [oldRecord objectForKey: @"c_recurrence_id"] - forKey: @"c_recurrence_id"]; -// [newRecord setObject: [NSNumber numberWithInt: [recurrenceId timeIntervalSince1970]] -// forKey: @"c_recurrence_id"]; + newRecord = [self fixupRecord: [component quickRecord]]; + [newRecord setObject: [NSNumber numberWithInt: 1] + forKey: @"c_iscycle"]; + oldRecord = [ma objectAtIndex: recordIndex]; + [newRecord setObject: [oldRecord objectForKey: @"c_recurrence_id"] + forKey: @"c_recurrence_id"]; - // The first instance date is added to the dictionary so it can - // be used by UIxCalListingActions to compute the DST offset. - [newRecord setObject: [fir startDate] forKey: @"cycleStartDate"]; + // The first instance date is added to the dictionary so it can + // be used by UIxCalListingActions to compute the DST offset. + [newRecord setObject: [fir startDate] forKey: @"cycleStartDate"]; - // We identified the record as an exception. - [newRecord setObject: [NSNumber numberWithInt: 1] - forKey: @"isException"]; - - [ma replaceObjectAtIndex: recordIndex withObject: newRecord]; - } - else - [ma removeObjectAtIndex: recordIndex]; + // We identified the record as an exception. + [newRecord setObject: [NSNumber numberWithInt: 1] + forKey: @"isException"]; + + [ma replaceObjectAtIndex: recordIndex withObject: newRecord]; } else [self errorWithFormat: @@ -1030,14 +1033,7 @@ firstInstanceCalendarDateRange: (NGCalendarDateRange *) fir // Retrieve the range of the first/master event component = [components objectAtIndex: 0]; dtstart = (iCalDateTime *) [component uniqueChildWithTag: @"dtstart"]; - firstStartDate = [[[[dtstart valuesForKey: @""] - lastObject] - lastObject] - asCalendarDate]; - firstEndDate = [firstStartDate addTimeInterval: [component occurenceInterval]]; - - firstRange = [NGCalendarDateRange calendarDateRangeWithStartDate: firstStartDate - endDate: firstEndDate]; + firstRange = [component firstOccurenceRange]; // ignores timezone eventTimeZone = [dtstart timeZone]; if (eventTimeZone) diff --git a/SoObjects/Appointments/SOGoAppointmentObject.m b/SoObjects/Appointments/SOGoAppointmentObject.m index 2f2eadb58..d54f0d1d4 100644 --- a/SoObjects/Appointments/SOGoAppointmentObject.m +++ b/SoObjects/Appointments/SOGoAppointmentObject.m @@ -1,5 +1,5 @@ /* - Copyright (C) 2007-2012 Inverse inc. + Copyright (C) 2007-2013 Inverse inc. Copyright (C) 2004-2005 SKYRIX Software AG This file is part of SOGo @@ -107,7 +107,7 @@ timeIntervalSinceDate: firstDate]; if ([newOccurence isAllDay]) { - nbrDays = ((float) abs (interval) / 86400) + 1; + nbrDays = ((float) abs (interval) / 86400); [newOccurence setAllDayWithStartDate: date duration: nbrDays]; } diff --git a/SoObjects/Appointments/iCalEvent+SOGo.m b/SoObjects/Appointments/iCalEvent+SOGo.m index b2be072e6..dc01b4284 100644 --- a/SoObjects/Appointments/iCalEvent+SOGo.m +++ b/SoObjects/Appointments/iCalEvent+SOGo.m @@ -1,6 +1,6 @@ /* iCalEvent+SOGo.m - this file is part of SOGo * - * Copyright (C) 2007-2011 Inverse inc. + * Copyright (C) 2007-2013 Inverse inc. * * Author: Wolfgang Sourdeau * Francis Lachapelle @@ -282,7 +282,7 @@ dates = [[[self uniqueChildWithTag: @"dtstart"] valuesForKey: @""] lastObject]; if ([dates count] > 0) { - start = [[dates lastObject] asCalendarDate]; + start = [[dates lastObject] asCalendarDate]; // ignores timezone end = [start addTimeInterval: [self occurenceInterval]]; firstRange = [NGCalendarDateRange calendarDateRangeWithStartDate: start diff --git a/SoObjects/Appointments/iCalRepeatableEntityObject+SOGo.h b/SoObjects/Appointments/iCalRepeatableEntityObject+SOGo.h index 1a50ef218..2d5233666 100644 --- a/SoObjects/Appointments/iCalRepeatableEntityObject+SOGo.h +++ b/SoObjects/Appointments/iCalRepeatableEntityObject+SOGo.h @@ -1,6 +1,6 @@ /* iCalRepeatableEntityObject+SOGo.h - this file is part of SOGo Copyright (C) 2004-2005 SKYRIX Software AG - Copyright (C) 2008 Inverse inc. + Copyright (C) 2008-2013 Inverse inc. This file is part of OpenGroupware.org. @@ -29,6 +29,7 @@ @interface iCalRepeatableEntityObject (SOGoExtensions) - (NSString *) cycleInfo; +- (NGCalendarDateRange *) firstOccurenceRange; - (BOOL) doesOccurOnDate: (NSCalendarDate *) occurenceDate; @end diff --git a/SoObjects/Appointments/iCalRepeatableEntityObject+SOGo.m b/SoObjects/Appointments/iCalRepeatableEntityObject+SOGo.m index d15760f64..4bbc30e25 100644 --- a/SoObjects/Appointments/iCalRepeatableEntityObject+SOGo.m +++ b/SoObjects/Appointments/iCalRepeatableEntityObject+SOGo.m @@ -1,5 +1,5 @@ /* - Copyright (C) 2008-2011 Inverse inc. + Copyright (C) 2008-2013 Inverse inc. Copyright (C) 2004-2005 SKYRIX Software AG This file is part of OpenGroupware.org. @@ -133,35 +133,15 @@ if (doesOccur) { // Retrieve the range of the first event - firstRange = [self firstOccurenceRange]; + firstRange = [self firstOccurenceRange]; // returns GMT dates // Set the range to check with respect to the event timezone (extracted from the start date) firstStartDate = (iCalDateTime *)[self uniqueChildWithTag: @"dtstart"]; timeZone = [(iCalDateTime *)firstStartDate timeZone]; if (timeZone) - { startDate = [(iCalTimeZone *)timeZone computedDateForDate: theOccurenceDate]; - } else - { startDate = theOccurenceDate; - if ([self isKindOfClass: [iCalEvent class]] && [(iCalEvent *) self isAllDay]) - { - // The event lasts all-day and has no timezone (floating); we convert the range of the first event - // to the occurence's timezone. - timeZone = [theOccurenceDate timeZone]; - offset = [(NSTimeZone *)timeZone secondsFromGMTForDate: [firstRange startDate]]; - firstStartDate = (NSCalendarDate *)[[firstRange startDate] dateByAddingYears:0 months:0 days:0 hours:0 minutes:0 - seconds:-offset]; - firstEndDate = (NSCalendarDate *)[[firstRange endDate] dateByAddingYears:0 months:0 days:0 hours:0 minutes:0 - seconds:-offset]; - [(NSCalendarDate *)firstStartDate setTimeZone: timeZone]; - [(NSCalendarDate *)firstEndDate setTimeZone: timeZone]; - - firstRange = [NGCalendarDateRange calendarDateRangeWithStartDate: firstStartDate - endDate: firstEndDate]; - } - } endDate = [startDate addTimeInterval: [self occurenceInterval]]; checkRange = [NGCalendarDateRange calendarDateRangeWithStartDate: startDate endDate: endDate];