fix(calendar): properly evalute last occurance freebusy

This commit is contained in:
Hivert Quentin
2025-06-17 11:31:00 +02:00
parent 8a907737de
commit 8766b7c6b3
4 changed files with 56 additions and 36 deletions
+14 -9
View File
@@ -55,7 +55,7 @@
- (NSArray *) recurrenceRangesWithinCalendarDateRange: (NGCalendarDateRange *) _r
{
NSMutableArray *ranges;
NSCalendarDate *firStart, *startDate, *endDate, *currentStartDate, *currentEndDate;
NSCalendarDate *firStart, *firEnd, *startDate, *endDate, *currentStartDate, *currentEndDate;
iCalByDayMask *dayMask;
long i, count, repeatCount;
unsigned interval;
@@ -63,6 +63,7 @@
//[self logWithFormat: @"Recurrence rule is %@", rrule];
firStart = [firstRange startDate];
firEnd = [firstRange endDate];
startDate = [_r startDate];
endDate = [_r endDate];
dayMask = nil;
@@ -84,13 +85,14 @@
// If rule is bound, check the bounds
if (![rrule isInfinite])
{
NSCalendarDate *until, *lastDate;
NSCalendarDate *until, *lastStartDate, *lastEndDate;
lastDate = nil;
lastStartDate = nil;
lastEndDate = nil;
until = [rrule untilDate];
if (until)
{
lastDate = until;
lastStartDate = until;
}
else
{
@@ -98,20 +100,23 @@
if (dayMask == nil)
// If there's no day mask, we can compute the date of the last
// occurrence of the recurrent rule.
lastDate = [firStart dateByAddingYears: 0 months: 0
lastStartDate = [firStart dateByAddingYears: 0 months: 0
days: (interval
* (repeatCount - 1))];
lastEndDate = [firEnd dateByAddingYears: 0 months: 0
days: (interval
* (repeatCount - 1))];
}
if (lastDate != nil)
if (lastStartDate != nil && lastEndDate != nil)
{
if ([lastDate compare: startDate] == NSOrderedAscending)
if ([lastEndDate compare: startDate] == NSOrderedAscending)
// Range starts after last occurrence
return nil;
if ([lastDate compare: endDate] == NSOrderedAscending)
if ([lastStartDate compare: endDate] == NSOrderedAscending)
// Range ends after last occurence; adjust end date
endDate = lastDate;
endDate = lastStartDate;
}
}
+14 -9
View File
@@ -185,7 +185,7 @@ static inline unsigned iCalDoWForNSDoW (int dow)
// TODO: check whether this is OK for multiday-events!
NSMutableArray *ranges;
NSTimeZone *timeZone;
NSCalendarDate *eventStartDate, *rStart, *rEnd, *until, *referenceDate;
NSCalendarDate *eventStartDate, *eventEndDate, *rStart, *rEnd, *untilStart, *untilEnd, *referenceDate;
int eventDayOfMonth;
unsigned monthIdxInRange, numberOfMonthsInRange, interval, repeatCount;
int diff, count;
@@ -199,12 +199,14 @@ static inline unsigned iCalDoWForNSDoW (int dow)
iCalByDayMask *byDayMask;
eventStartDate = [firstRange startDate];
eventEndDate = [firstRange endDate];
eventDayOfMonth = [eventStartDate dayOfMonth];
timeZone = [eventStartDate timeZone];
rStart = [_r startDate];
rEnd = [_r endDate];
interval = [rrule repeatInterval];
until = nil;
untilStart = nil;
untilEnd = nil;
repeatCount = [rrule repeatCount];
byMonth = [rrule byMonth];
byMonthDay = [rrule byMonthDay];
@@ -218,24 +220,27 @@ static inline unsigned iCalDoWForNSDoW (int dow)
{
// When there's no BYxxx mask, we can find the date of the last
// occurrence.
until = [eventStartDate dateByAddingYears: 0
untilStart = [eventStartDate dateByAddingYears: 0
months: (interval * (repeatCount - 1))
days: 0];
untilEnd = [eventEndDate dateByAddingYears: 0
months: (interval * (repeatCount - 1))
days: 0];
}
else
{
until = [rrule untilDate];
untilStart = [rrule untilDate];
}
}
if (until != nil)
if (untilStart != nil)
{
if ([until compare: rStart] == NSOrderedAscending)
if ([untilEnd compare: rStart] == NSOrderedAscending)
// Range starts after last occurrence
return nil;
if ([until compare: rEnd] == NSOrderedAscending)
if ([untilStart compare: rEnd] == NSOrderedAscending)
// Range ends after last occurence; adjust end date
rEnd = until;
rEnd = untilStart;
}
if (byMonth && [byMonth count] > 0)
@@ -441,7 +446,7 @@ static inline unsigned iCalDoWForNSDoW (int dow)
start = [cursor dateByAddingYears: 0 months: 0 days: (dom - 1)];
doCont = [self _addInstanceWithStartDate: start
limitDate: until
limitDate: untilStart
limitRange: _r
toArray: ranges];
//NSLog(@"*** MONTHLY [%i/%i] adding %@%@ (count = %i)", dom, numDaysInMonth, start, (doCont?@"":@" .. NOT!"), count);
+14 -9
View File
@@ -64,7 +64,7 @@
- (NSArray *) recurrenceRangesWithinCalendarDateRange: (NGCalendarDateRange *) _r
{
NSMutableArray *ranges;
NSCalendarDate *firStart, *startDate, *endDate, *currentStartDate, *currentEndDate;
NSCalendarDate *firStart, *firEnd, *startDate, *endDate, *currentStartDate, *currentEndDate;
long i, repeatCount, count;
unsigned interval;
iCalByDayMask *dayMask;
@@ -73,6 +73,7 @@
//[self logWithFormat: @"Recurrence rule is %@", rrule];
firStart = [firstRange startDate];
firEnd = [firstRange endDate];
startDate = [_r startDate];
endDate = [_r endDate];
dayMask = nil;
@@ -95,31 +96,35 @@
// If rule is bound, check the bounds
if (![rrule isInfinite])
{
NSCalendarDate *until, *lastDate;
NSCalendarDate *until, *lastStartDate, *lastEndDate;
lastDate = nil;
lastStartDate = nil;
lastEndDate = nil;
until = [rrule untilDate];
if (until)
lastDate = until;
lastStartDate = until;
else
{
repeatCount = [rrule repeatCount];
if (dayMask == nil)
// When there's no BYxxx mask, we can find the date of the last
// occurrence.
lastDate = [firStart dateByAddingYears: 0 months: 0
lastStartDate = [firStart dateByAddingYears: 0 months: 0
days: (interval
* (repeatCount - 1) * 7)];
lastEndDate = [firEnd dateByAddingYears: 0 months: 0
days: (interval
* (repeatCount - 1) * 7)];
}
if (lastDate != nil)
if (lastStartDate != nil && lastEndDate != nil)
{
if ([lastDate compare: startDate] == NSOrderedAscending)
if ([lastEndDate compare: startDate] == NSOrderedAscending)
// Range starts after last occurrence
return nil;
if ([lastDate compare: endDate] == NSOrderedAscending)
if ([lastStartDate compare: endDate] == NSOrderedAscending)
// Range ends after last occurence; adjust end date
endDate = [lastDate addTimeInterval: [firstRange duration]];
endDate = [lastStartDate addTimeInterval: [firstRange duration]];
}
}
+14 -9
View File
@@ -44,13 +44,14 @@
{
NSMutableArray *ranges;
NSArray *byMonth;
NSCalendarDate *firStart, *lastDate, *rStart, *rEnd, *until, *referenceDate, *rTemp;
NSCalendarDate *firStart, *firEnd, *lastStartDate, *lastEndDate, *rStart, *rEnd, *until, *referenceDate, *rTemp;
NSInteger *hoursOfOffset;
iCalMonthlyRecurrenceCalculator *monthlyCalc;
unsigned j, yearIdxInRange, numberOfYearsInRange, count, interval, monthDiff;
int diff, repeatCount, currentMonth, origNbDaysInMonth;
firStart = [firstRange startDate];
firEnd = [firstRange endDate];
rStart = [_r startDate];
rEnd = [_r endDate];
interval = [rrule repeatInterval];
@@ -71,33 +72,37 @@
// If rule is bound, check the bounds
if (![rrule isInfinite])
{
lastDate = nil;
lastStartDate = nil;
lastEndDate = nil;
until = [rrule untilDate];
repeatCount = [rrule repeatCount];
if (until)
{
lastDate = until;
lastStartDate = until;
}
if (repeatCount > 0)
{
if (lastDate == nil && ![rrule hasByMask])
if (lastStartDate == nil && ![rrule hasByMask])
// When there's no BYxxx mask, we can find the date of the last
// occurrence.
lastDate = [firStart dateByAddingYears: (interval * (repeatCount - 1))
lastStartDate = [firStart dateByAddingYears: (interval * (repeatCount - 1))
months: 0
days: 0];
lastEndDate = [firEnd dateByAddingYears: (interval * (repeatCount - 1))
months: 0
days: 0];
referenceDate = firStart;
}
if (lastDate != nil)
if (lastStartDate != nil)
{
if ([lastDate compare: rStart] == NSOrderedAscending)
if ([lastEndDate compare: rStart] == NSOrderedAscending)
// Range starts after last occurrence
return nil;
if ([lastDate compare: rEnd] == NSOrderedAscending)
if ([lastStartDate compare: rEnd] == NSOrderedAscending)
// Range ends after last occurence; adjust end date
rEnd = [lastDate addTimeInterval: [firstRange duration]];
rEnd = [lastStartDate addTimeInterval: [firstRange duration]];
}
}