Fix handling of weekly recurrence rule with count

This fixes some corner cases when computing the freebusy and therefore
when verifying for resource conflicts.
pull/225/head
Francis Lachapelle 2016-11-04 16:44:14 -04:00
parent c35e074842
commit 168a2ddd18
4 changed files with 21 additions and 17 deletions

View File

@ -97,6 +97,7 @@ extern NSString *iCalWeekDayString[];
/* count and untilDate are mutually exclusive */ /* count and untilDate are mutually exclusive */
- (BOOL) hasRepeatCount;
- (void) setRepeatCount: (int) _repeatCount; - (void) setRepeatCount: (int) _repeatCount;
- (int) repeatCount; - (int) repeatCount;

View File

@ -403,6 +403,11 @@ NSString *iCalWeekDayString[] = { @"SU", @"MO", @"TU", @"WE", @"TH", @"FR",
return [[self flattenedValuesForKey: @"count"] intValue]; return [[self flattenedValuesForKey: @"count"] intValue];
} }
- (BOOL) hasRepeatCount
{
return [[self flattenedValuesForKey: @"count"] length] > 0;
}
- (void) setCount: (NSString *) _count - (void) setCount: (NSString *) _count
{ {
[self setSingleValue: _count forKey: @"count"]; [self setSingleValue: _count forKey: @"count"];

View File

@ -68,6 +68,7 @@
long i, repeatCount, count; long i, repeatCount, count;
unsigned interval; unsigned interval;
iCalByDayMask *dayMask; iCalByDayMask *dayMask;
BOOL hasRepeatCount;
[self logWithFormat: @"Weekly %@", rrule]; [self logWithFormat: @"Weekly %@", rrule];
@ -76,6 +77,7 @@
endDate = [_r endDate]; endDate = [_r endDate];
dayMask = nil; dayMask = nil;
repeatCount = 0; repeatCount = 0;
hasRepeatCount = [rrule hasRepeatCount];
if ([endDate compare: firStart] == NSOrderedAscending) if ([endDate compare: firStart] == NSOrderedAscending)
// Range ends before first occurrence // Range ends before first occurrence
@ -113,7 +115,7 @@
return nil; return nil;
if ([lastDate compare: endDate] == NSOrderedAscending) if ([lastDate compare: endDate] == NSOrderedAscending)
// Range ends after last occurence; adjust end date // Range ends after last occurence; adjust end date
endDate = lastDate; endDate = [lastDate addTimeInterval: [firstRange duration]];
} }
} }
@ -129,9 +131,7 @@
[currentStartDate compare: endDate] == NSOrderedSame) [currentStartDate compare: endDate] == NSOrderedSame)
{ {
currentEndDate = [currentStartDate addTimeInterval: [firstRange duration]]; currentEndDate = [currentStartDate addTimeInterval: [firstRange duration]];
if ([startDate compare: currentStartDate] == NSOrderedAscending || if ([startDate compare: currentEndDate] == NSOrderedAscending)
[startDate compare: currentStartDate] == NSOrderedSame ||
[startDate compare: currentEndDate] == NSOrderedAscending)
{ {
NGCalendarDateRange *r; NGCalendarDateRange *r;
@ -156,9 +156,9 @@
BOOL isRecurrence = NO; BOOL isRecurrence = NO;
NSInteger week; NSInteger week;
if (repeatCount > 0 || currentEndDate = [currentStartDate addTimeInterval: [firstRange duration]];
[startDate compare: currentStartDate] == NSOrderedAscending || if (hasRepeatCount ||
[startDate compare: currentStartDate] == NSOrderedSame) [startDate compare: currentEndDate] == NSOrderedAscending)
{ {
// If the rule count is defined, stop once the count is reached. // If the rule count is defined, stop once the count is reached.
if ([currentStartDate compare: firStart] == NSOrderedSame) if ([currentStartDate compare: firStart] == NSOrderedSame)
@ -181,10 +181,8 @@
count++; count++;
if (repeatCount > 0 && count > repeatCount) if (repeatCount > 0 && count > repeatCount)
break; break;
currentEndDate = [currentStartDate addTimeInterval: [firstRange duration]];
r = [NGCalendarDateRange calendarDateRangeWithStartDate: currentStartDate r = [NGCalendarDateRange calendarDateRangeWithStartDate: currentStartDate
endDate: currentEndDate]; endDate: currentEndDate];
if ([_r doesIntersectWithDateRange: r]) if ([_r doesIntersectWithDateRange: r])
{ {
[ranges addObject: r]; [ranges addObject: r];

View File

@ -177,15 +177,15 @@
NSCalendarDate *date; NSCalendarDate *date;
date = [self lastPossibleRecurrenceStartDate]; date = [self lastPossibleRecurrenceStartDate];
if (!date) if (date)
{ date = [date addTimeInterval: [self durationAsTimeInterval]];
/* this could also be *nil*, but in the end it makes the fetchspecs else
more complex - thus we set it to a "reasonable" distant future */ /* this could also be *nil*, but in the end it makes the fetchspecs
date = iCalDistantFuture; more complex - thus we set it to a "reasonable" distant future */
} date = iCalDistantFuture;
[row setObject: [self quickRecordDateAsNumber: date [row setObject: [self quickRecordDateAsNumber: date
withOffset: 0 forAllDay: NO] withOffset: 0 forAllDay: NO]
forKey: @"c_cycleenddate"]; forKey: @"c_cycleenddate"];
[row setObject: [self cycleInfo] forKey: @"c_cycleinfo"]; [row setObject: [self cycleInfo] forKey: @"c_cycleinfo"];
} }