Fix exceptions of recurring all-day events

pull/8/head
Francis Lachapelle 2013-01-21 14:11:38 -05:00
parent ddc9a1b3f5
commit 5bbb5df2a8
5 changed files with 42 additions and 65 deletions

View File

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

View File

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

View File

@ -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 <wsourdeau@inverse.ca>
* Francis Lachapelle <flachapelle@inverse.ca>
@ -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

View File

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

View File

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