/*
- Copyright (C) 2004-2005 SKYRIX Software AG
-
- This file is part of SOPE.
-
- SOPE is free software; you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the
- Free Software Foundation; either version 2, or (at your option) any
- later version.
-
- SOPE is distributed in the hope that it will be useful, but WITHOUT ANY
- WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
- License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with SOPE; see the file COPYING. If not, write to the
- Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
- 02111-1307, USA.
+ Copyright (C) 2004-2005 SKYRIX Software AG
+
+ This file is part of SOPE.
+
+ SOPE is free software; you can redistribute it and/or modify it under
+ the terms of the GNU Lesser General Public License as published by the
+ Free Software Foundation; either version 2, or (at your option) any
+ later version.
+
+ SOPE is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+ License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with SOPE; see the file COPYING. If not, write to the
+ Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA.
*/
#include "iCalRecurrenceCalculator.h"
/* class cluster */
-@interface iCalDailyRecurrenceCalculator : iCalRecurrenceCalculator
-{
-}
-@end
-
-@interface iCalWeeklyRecurrenceCalculator : iCalRecurrenceCalculator
-{
-}
-@end
-
-@interface iCalMonthlyRecurrenceCalculator : iCalRecurrenceCalculator
-{
-}
-@end
-
-@interface iCalYearlyRecurrenceCalculator : iCalRecurrenceCalculator
-{
-}
-@end
/* Private */
NSCalendarDateClass = [NSCalendarDate class];
iCalRecurrenceRuleClass = [iCalRecurrenceRule class];
- dailyCalcClass = [iCalDailyRecurrenceCalculator class];
- weeklyCalcClass = [iCalWeeklyRecurrenceCalculator class];
- monthlyCalcClass = [iCalMonthlyRecurrenceCalculator class];
- yearlyCalcClass = [iCalYearlyRecurrenceCalculator class];
+ dailyCalcClass = NSClassFromString(@"iCalDailyRecurrenceCalculator");
+ weeklyCalcClass = NSClassFromString(@"iCalWeeklyRecurrenceCalculator");
+ monthlyCalcClass = NSClassFromString(@"iCalMonthlyRecurrenceCalculator");
+ yearlyCalcClass = NSClassFromString(@"iCalYearlyRecurrenceCalculator");
}
/* factory */
}
@end /* iCalRecurrenceCalculator */
-
-
-@implementation iCalDailyRecurrenceCalculator
-
-- (NSArray *)recurrenceRangesWithinCalendarDateRange:(NGCalendarDateRange *)_r {
- NSMutableArray *ranges;
- NSCalendarDate *firStart;
- long i, jnFirst, jnStart, jnEnd, startEndCount;
- unsigned interval;
-
- firStart = [self->firstRange startDate];
- jnFirst = [firStart julianNumber];
- jnEnd = [[_r endDate] julianNumber];
-
- if (jnFirst > jnEnd)
- return nil;
-
- jnStart = [[_r startDate] julianNumber];
- interval = [self->rrule repeatInterval];
-
- /* if rule is bound, check the bounds */
- if (![self->rrule isInfinite]) {
- NSCalendarDate *until;
- long jnRuleLast;
-
- until = [self->rrule untilDate];
- if (until) {
- if ([until compare:[_r startDate]] == NSOrderedAscending)
- return nil;
- jnRuleLast = [until julianNumber];
- }
- else {
- jnRuleLast = (interval * [self->rrule repeatCount])
- + jnFirst;
- if (jnRuleLast < jnStart)
- return nil;
- }
- /* jnStart < jnRuleLast < jnEnd ? */
- if (jnEnd > jnRuleLast)
- jnEnd = jnRuleLast;
- }
-
- startEndCount = (jnEnd - jnStart) + 1;
- ranges = [NSMutableArray arrayWithCapacity:startEndCount];
- for (i = 0 ; i < startEndCount; i++) {
- long jnCurrent;
-
- jnCurrent = jnStart + i;
- if (jnCurrent >= jnFirst) {
- long jnTest;
-
- jnTest = jnCurrent - jnFirst;
- if ((jnTest % interval) == 0) {
- NSCalendarDate *start, *end;
- NGCalendarDateRange *r;
-
- start = [NSCalendarDate dateForJulianNumber:jnCurrent];
- [start setTimeZone:[firStart timeZone]];
- start = [start hour: [firStart hourOfDay]
- minute:[firStart minuteOfHour]
- second:[firStart secondOfMinute]];
- end = [start addTimeInterval:[self->firstRange duration]];
- r = [NGCalendarDateRange calendarDateRangeWithStartDate:start
- endDate:end];
- if ([_r containsDateRange:r])
- [ranges addObject:r];
- }
- }
- }
- return ranges;
-}
-
-- (NSCalendarDate *)lastInstanceStartDate {
- if ([self->rrule repeatCount] > 0) {
- long jnFirst, jnRuleLast;
- NSCalendarDate *firStart, *until;
-
- firStart = [self->firstRange startDate];
- jnFirst = [firStart julianNumber];
- jnRuleLast = ([self->rrule repeatInterval] *
- [self->rrule repeatCount]) +
- jnFirst;
- until = [NSCalendarDate dateForJulianNumber:jnRuleLast];
- until = [until hour: [firStart hourOfDay]
- minute:[firStart minuteOfHour]
- second:[firStart secondOfMinute]];
- return until;
- }
- return [super lastInstanceStartDate];
-}
-
-@end /* iCalDailyRecurrenceCalculator */
-
-
-/*
- TODO: If BYDAY is specified, lastInstanceStartDate and recurrences will
- differ significantly!
-*/
-@implementation iCalWeeklyRecurrenceCalculator
-
-- (NSArray *)recurrenceRangesWithinCalendarDateRange:(NGCalendarDateRange *)_r {
- NSMutableArray *ranges;
- NSCalendarDate *firStart;
- long i, jnFirst, jnStart, jnEnd, startEndCount;
- unsigned interval, byDayMask;
-
- firStart = [self->firstRange startDate];
- jnFirst = [firStart julianNumber];
- jnEnd = [[_r endDate] julianNumber];
-
- if (jnFirst > jnEnd)
- return nil;
-
- jnStart = [[_r startDate] julianNumber];
- interval = [self->rrule repeatInterval];
-
- /* if rule is bound, check the bounds */
- if (![self->rrule isInfinite]) {
- NSCalendarDate *until;
- long jnRuleLast;
-
- until = [self->rrule untilDate];
- if (until) {
- if ([until compare:[_r startDate]] == NSOrderedAscending)
- return nil;
- jnRuleLast = [until julianNumber];
- }
- else {
- jnRuleLast = (interval * [self->rrule repeatCount] * 7)
- + jnFirst;
- if (jnRuleLast < jnStart)
- return nil;
- }
- /* jnStart < jnRuleLast < jnEnd ? */
- if (jnEnd > jnRuleLast)
- jnEnd = jnRuleLast;
- }
-
- startEndCount = (jnEnd - jnStart) + 1;
- ranges = [NSMutableArray arrayWithCapacity:startEndCount];
- byDayMask = [self->rrule byDayMask];
- if (!byDayMask) {
- for (i = 0 ; i < startEndCount; i++) {
- long jnCurrent;
-
- jnCurrent = jnStart + i;
- if (jnCurrent >= jnFirst) {
- long jnDiff;
-
- jnDiff = jnCurrent - jnFirst; /* difference in days */
- if ((jnDiff % (interval * 7)) == 0) {
- NSCalendarDate *start, *end;
- NGCalendarDateRange *r;
-
- start = [NSCalendarDate dateForJulianNumber:jnCurrent];
- [start setTimeZone:[firStart timeZone]];
- start = [start hour: [firStart hourOfDay]
- minute:[firStart minuteOfHour]
- second:[firStart secondOfMinute]];
- end = [start addTimeInterval:[self->firstRange duration]];
- r = [NGCalendarDateRange calendarDateRangeWithStartDate:start
- endDate:end];
- if ([_r containsDateRange:r])
- [ranges addObject:r];
- }
- }
- }
- }
- else {
- long jnFirstWeekStart, weekStartOffset;
-
- /* calculate jnFirst's week start - this depends on our setting of week
- start */
- weekStartOffset = [self offsetFromSundayForJulianNumber:jnFirst] -
- [self offsetFromSundayForCurrentWeekStart];
-
- jnFirstWeekStart = jnFirst - weekStartOffset;
-
- for (i = 0 ; i < startEndCount; i++) {
- long jnCurrent;
-
- jnCurrent = jnStart + i;
- if (jnCurrent >= jnFirst) {
- long jnDiff;
-
- /* we need to calculate a difference in weeks */
- jnDiff = (jnCurrent - jnFirstWeekStart) % 7;
- if ((jnDiff % interval) == 0) {
- BOOL isRecurrence = NO;
-
- if (jnCurrent == jnFirst) {
- isRecurrence = YES;
- }
- else {
- iCalWeekDay weekDay;
-
- weekDay = [self weekDayForJulianNumber:jnCurrent];
- isRecurrence = (weekDay & [self->rrule byDayMask]) ? YES : NO;
- }
- if (isRecurrence) {
- NSCalendarDate *start, *end;
- NGCalendarDateRange *r;
-
- start = [NSCalendarDate dateForJulianNumber:jnCurrent];
- [start setTimeZone:[firStart timeZone]];
- start = [start hour: [firStart hourOfDay]
- minute:[firStart minuteOfHour]
- second:[firStart secondOfMinute]];
- end = [start addTimeInterval:[self->firstRange duration]];
- r = [NGCalendarDateRange calendarDateRangeWithStartDate:start
- endDate:end];
- if ([_r containsDateRange:r])
- [ranges addObject:r];
- }
- }
- }
- }
- }
- return ranges;
-}
-
-- (NSCalendarDate *)lastInstanceStartDate {
- if ([self->rrule repeatCount] > 0) {
- long jnFirst, jnRuleLast;
- NSCalendarDate *firStart, *until;
-
- firStart = [self->firstRange startDate];
- jnFirst = [firStart julianNumber];
- jnRuleLast = ([self->rrule repeatInterval] *
- [self->rrule repeatCount] * 7) +
- jnFirst;
- until = [NSCalendarDate dateForJulianNumber:jnRuleLast];
- until = [until hour: [firStart hourOfDay]
- minute:[firStart minuteOfHour]
- second:[firStart secondOfMinute]];
- return until;
- }
- return [super lastInstanceStartDate];
-}
-
-@end /* iCalWeeklyRecurrenceCalculator */
-
-@implementation iCalMonthlyRecurrenceCalculator
-
-- (NSArray *)recurrenceRangesWithinCalendarDateRange:(NGCalendarDateRange *)_r {
- NSMutableArray *ranges;
- NSCalendarDate *firStart, *rStart, *rEnd, *until;
- unsigned i, count, interval;
- int diff;
-
- firStart = [self->firstRange startDate];
- rStart = [_r startDate];
- rEnd = [_r endDate];
- interval = [self->rrule repeatInterval];
- until = [self lastInstanceStartDate];
-
- if (until) {
- if ([until compare:rStart] == NSOrderedAscending)
- return nil;
- if ([until compare:rEnd] == NSOrderedDescending)
- rEnd = until;
- }
-
- diff = [firStart monthsBetweenDate:rStart];
- if ((diff != 0) && [rStart compare:firStart] == NSOrderedAscending)
- diff = -diff;
-
- count = [rStart monthsBetweenDate:rEnd] + 1;
- ranges = [NSMutableArray arrayWithCapacity:count];
- for (i = 0 ; i < count; i++) {
- int test;
-
- test = diff + i;
- if ((test >= 0) && (test % interval) == 0) {
- NSCalendarDate *start, *end;
- NGCalendarDateRange *r;
-
- start = [firStart dateByAddingYears:0
- months:diff + i
- days:0];
- [start setTimeZone:[firStart timeZone]];
- end = [start addTimeInterval:[self->firstRange duration]];
- r = [NGCalendarDateRange calendarDateRangeWithStartDate:start
- endDate:end];
- if ([_r containsDateRange:r])
- [ranges addObject:r];
- }
- }
- return ranges;
-}
-
-- (NSCalendarDate *)lastInstanceStartDate {
- if ([self->rrule repeatCount] > 0) {
- NSCalendarDate *until;
- unsigned months, interval;
-
- interval = [self->rrule repeatInterval];
- months = [self->rrule repeatCount] * interval;
- until = [[self->firstRange startDate] dateByAddingYears:0
- months:months
- days:0];
- return until;
- }
- return [super lastInstanceStartDate];
-}
-
-@end /* iCalMonthlyRecurrenceCalculator */
-
-@implementation iCalYearlyRecurrenceCalculator
-
-- (NSArray *)recurrenceRangesWithinCalendarDateRange:(NGCalendarDateRange *)_r {
- NSMutableArray *ranges;
- NSCalendarDate *firStart, *rStart, *rEnd, *until;
- unsigned i, count, interval;
- int diff;
-
- firStart = [self->firstRange startDate];
- rStart = [_r startDate];
- rEnd = [_r endDate];
- interval = [self->rrule repeatInterval];
- until = [self lastInstanceStartDate];
-
- if (until) {
- if ([until compare:rStart] == NSOrderedAscending)
- return nil;
- if ([until compare:rEnd] == NSOrderedDescending)
- rEnd = until;
- }
-
- diff = [firStart yearsBetweenDate:rStart];
- if ((diff != 0) && [rStart compare:firStart] == NSOrderedAscending)
- diff = -diff;
-
- count = [rStart yearsBetweenDate:rEnd] + 1;
- ranges = [NSMutableArray arrayWithCapacity:count];
- for (i = 0 ; i < count; i++) {
- int test;
-
- test = diff + i;
- if ((test >= 0) && (test % interval) == 0) {
- NSCalendarDate *start, *end;
- NGCalendarDateRange *r;
-
- start = [firStart dateByAddingYears:diff + i
- months:0
- days:0];
- [start setTimeZone:[firStart timeZone]];
- end = [start addTimeInterval:[self->firstRange duration]];
- r = [NGCalendarDateRange calendarDateRangeWithStartDate:start
- endDate:end];
- if ([_r containsDateRange:r])
- [ranges addObject:r];
- }
- }
- return ranges;
-}
-
-- (NSCalendarDate *)lastInstanceStartDate {
- if ([self->rrule repeatCount] > 0) {
- NSCalendarDate *until;
- unsigned years, interval;
-
- interval = [self->rrule repeatInterval];
- years = [self->rrule repeatCount] * interval;
- until = [[self->firstRange startDate] dateByAddingYears:years
- months:0
- days:0];
- return until;
- }
- return [super lastInstanceStartDate];
-}
-
-@end /* iCalYearlyRecurrenceCalculator */