diff --git a/ChangeLog b/ChangeLog index 2d7d42a74..5d0c1dff7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +2011-01-14 Francis Lachapelle + + * SoObjects/Appointments/iCalRepeatableEntityObject+SOGo.m + (-doesOccurOnDate:): exception rules be adjusted to the event's + timezone since the recurrence calculation is also based on the + event's timezone. + + * SoObjects/Appointments/SOGoAppointmentFolder.m + (-_flattenCycleRecord:forRange:intoArray:): idem. + 2011-01-13 Francis Lachapelle * SoObjects/Appointments/iCalRepeatableEntityObject+SOGo.m diff --git a/SOPE/NGCards/ChangeLog b/SOPE/NGCards/ChangeLog index 4f2ba4898..a4aeed3ff 100644 --- a/SOPE/NGCards/ChangeLog +++ b/SOPE/NGCards/ChangeLog @@ -1,3 +1,13 @@ +2011-01-14 Francis Lachapelle + + * iCalTimeZone.m (-computedDateForString:): new method that + returns a date adjusted with respect to this vTimeZone. + (-computedDatesForStrings:): idem but for multiple dates. + + * iCalRepeatableEntityObject.m + (-exceptionDatesWithEventTimeZone:): new method that returns the + exception dates for the event, but adjusted to the event's timezone. + 2011-01-13 Francis Lachapelle * iCalTimeZone.m (-computedDateForDate:): Was diff --git a/SOPE/NGCards/iCalRepeatableEntityObject.h b/SOPE/NGCards/iCalRepeatableEntityObject.h index d89cd03ed..4e4e577b8 100644 --- a/SOPE/NGCards/iCalRepeatableEntityObject.h +++ b/SOPE/NGCards/iCalRepeatableEntityObject.h @@ -33,6 +33,7 @@ */ @class NSCalendarDate, NSMutableArray, NGCalendarDateRange; +@class iCalTimeZone; @interface iCalRepeatableEntityObject : iCalEntityObject // { @@ -56,6 +57,7 @@ - (void)addToExceptionDates:(NSCalendarDate *)_date; - (BOOL)hasExceptionDates; - (NSArray *)exceptionDates; +- (NSArray *)exceptionDatesWithEventTimeZone:(iCalTimeZone*)theTimeZone; - (BOOL)isRecurrent; - (BOOL)isWithinCalendarDateRange:(NGCalendarDateRange *)_range diff --git a/SOPE/NGCards/iCalRepeatableEntityObject.m b/SOPE/NGCards/iCalRepeatableEntityObject.m index 6f8d8ccf4..3094474db 100644 --- a/SOPE/NGCards/iCalRepeatableEntityObject.m +++ b/SOPE/NGCards/iCalRepeatableEntityObject.m @@ -29,6 +29,7 @@ #import "NSCalendarDate+NGCards.h" #import "iCalDateTime.h" +#import "iCalTimeZone.h" #import "iCalRecurrenceRule.h" #import "iCalRecurrenceCalculator.h" #import "iCalRepeatableEntityObject.h" @@ -130,6 +131,10 @@ return ([[self childrenWithTag: @"exdate"] count] > 0); } +/** + * Return the exception dates of the event in GMT. + * @return an array of strings. + */ - (NSArray *) exceptionDates { NSArray *exDates; @@ -157,6 +162,39 @@ return dates; } +/** + * Returns the exception dates for the event, but adjusted to the event timezone. + * Used when calculating a recurrence rule. + * @param theTimeZone the timezone of the event. + * @see [iCalTimeZone computedDatesForStrings:] + * @return the exception dates for the event, adjusted to the event timezone. + */ +- (NSArray *) exceptionDatesWithEventTimeZone: (iCalTimeZone *) theTimeZone +{ + NSArray *exDates; + NSMutableArray *dates; + NSEnumerator *dateList; + NSCalendarDate *exDate; + NSString *dateString; + unsigned i; + + dates = [NSMutableArray array]; + dateList = [[self childrenWithTag: @"exdate"] objectEnumerator]; + + while ((dateString = [dateList nextObject])) + { + exDates = [(iCalDateTime*) dateString values]; + for (i = 0; i < [exDates count]; i++) + { + dateString = [exDates objectAtIndex: i]; + exDate = [theTimeZone computedDateForString: dateString]; + [dates addObject: exDate]; + } + } + + return dates; +} + /* Convenience */ - (BOOL) isRecurrent diff --git a/SOPE/NGCards/iCalTimeZone.h b/SOPE/NGCards/iCalTimeZone.h index 339df3711..a44bddbee 100644 --- a/SOPE/NGCards/iCalTimeZone.h +++ b/SOPE/NGCards/iCalTimeZone.h @@ -36,6 +36,8 @@ - (NSString *) tzId; - (iCalTimeZonePeriod *) periodForDate: (NSCalendarDate *) date; - (NSCalendarDate *) computedDateForDate: (NSCalendarDate *) theDate; +- (NSCalendarDate *) computedDateForString: (NSString *) theDate; +- (NSMutableArray *) computedDatesForStrings: (NSArray *) theDates; - (NSString *) dateTimeStringForDate: (NSCalendarDate *) date; - (NSString *) dateStringForDate: (NSCalendarDate *) date; - (NSCalendarDate *) dateForDateTimeString: (NSString *) string; diff --git a/SOPE/NGCards/iCalTimeZone.m b/SOPE/NGCards/iCalTimeZone.m index 9ca51dc88..156110f63 100644 --- a/SOPE/NGCards/iCalTimeZone.m +++ b/SOPE/NGCards/iCalTimeZone.m @@ -209,6 +209,49 @@ static NSMutableDictionary *cache; second: [[self periodForDate: theDate] secondsOffsetFromGMT]]; } +/** + * Adjust a date with respect to this vTimeZone. + * @param theDate the string representing a date. + * @return a new GMT date adjusted with the offset of this timezone. + */ +- (NSCalendarDate *) computedDateForString: (NSString *) theDate +{ + NSCalendarDate *tmpDate; + NSTimeZone *utc; + + utc = [NSTimeZone timeZoneWithName: @"GMT"]; + tmpDate = [theDate asCalendarDate]; + [tmpDate setTimeZone: utc]; + + return [tmpDate addYear: 0 month: 0 day: 0 + hour: 0 minute: 0 + second: [[self periodForDate: tmpDate] secondsOffsetFromGMT]]; +} + +/** + * Adjust multiple dates with respect to this vTimeZone. + * @param theDates an array of strings representing dates. + * @param an array of NSCalendarDate objects. + */ +- (NSMutableArray *) computedDatesForStrings: (NSArray *) theDates +{ + NSCalendarDate *date; + NSMutableArray *dates; + NSEnumerator *dateList; + NSString *dateString; + + dates = [NSMutableArray array]; + dateList = [theDates objectEnumerator]; + + while ((dateString = [dateList nextObject])) + { + date = [self computedDateForString: dateString]; + [dates addObject: date]; + } + + return dates; +} + - (NSString *) dateTimeStringForDate: (NSCalendarDate *) date { return [[self computedDateForDate: date] diff --git a/SoObjects/Appointments/SOGoAppointmentFolder.m b/SoObjects/Appointments/SOGoAppointmentFolder.m index ff0c7147d..4e52dba15 100644 --- a/SoObjects/Appointments/SOGoAppointmentFolder.m +++ b/SoObjects/Appointments/SOGoAppointmentFolder.m @@ -899,7 +899,7 @@ firstInstanceCalendarDateRange: (NGCalendarDateRange *) fir // Calculate the occurrences for the given range rules = [cycleinfo objectForKey: @"rules"]; exRules = [cycleinfo objectForKey: @"exRules"]; - exDates = [cycleinfo objectForKey: @"exDates"]; + exDates = [eventTimeZone computedDatesForStrings: [cycleinfo objectForKey: @"exDates"]]; ranges = [iCalRecurrenceCalculator recurrenceRangesWithinCalendarDateRange: theRange firstInstanceCalendarDateRange: firstRange recurrenceRules: rules diff --git a/SoObjects/Appointments/iCalRepeatableEntityObject+SOGo.m b/SoObjects/Appointments/iCalRepeatableEntityObject+SOGo.m index 70984bf36..6677ca652 100644 --- a/SoObjects/Appointments/iCalRepeatableEntityObject+SOGo.m +++ b/SoObjects/Appointments/iCalRepeatableEntityObject+SOGo.m @@ -118,6 +118,7 @@ NGCalendarDateRange *checkRange, *firstRange; NSCalendarDate *startDate, *endDate; iCalDateTime *firstStartDate; + iCalTimeZone *eventTimeZone; BOOL doesOccur; doesOccur = [self isRecurrent]; @@ -128,7 +129,8 @@ // Set the range to check with respect to the event timezone (extracted from the start date) firstStartDate = (iCalDateTime *)[self uniqueChildWithTag: @"dtstart"]; - startDate = [[firstStartDate timeZone] computedDateForDate: theOccurenceDate]; + eventTimeZone = [firstStartDate timeZone]; + startDate = [eventTimeZone computedDateForDate: theOccurenceDate]; endDate = [startDate addTimeInterval: [self occurenceInterval]]; checkRange = [NGCalendarDateRange calendarDateRangeWithStartDate: startDate endDate: endDate]; @@ -138,7 +140,7 @@ firstInstanceCalendarDateRange: firstRange recurrenceRules: [self recurrenceRules] exceptionRules: [self exceptionRules] - exceptionDates: [self exceptionDates]]; + exceptionDates: [self exceptionDatesWithEventTimeZone: eventTimeZone]]; doesOccur = [ranges dateRangeArrayContainsDate: startDate]; }