2 Copyright (C) 2000-2005 SKYRIX Software AG
4 This file is part of SOPE.
6 SOPE is free software; you can redistribute it and/or modify it under
7 the terms of the GNU Lesser General Public License as published by the
8 Free Software Foundation; either version 2, or (at your option) any
11 SOPE is distributed in the hope that it will be useful, but WITHOUT ANY
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
14 License for more details.
16 You should have received a copy of the GNU Lesser General Public
17 License along with SOPE; see the file COPYING. If not, write to the
18 Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
22 #include "iCalEvent.h"
23 #include "iCalPerson.h"
24 #include "iCalEventChanges.h"
25 #include "iCalRecurrenceRule.h"
26 #include "iCalRenderer.h"
27 #include <NGExtensions/NGCalendarDateRange.h>
30 @interface NSString(DurationTimeInterval)
31 - (NSTimeInterval)durationAsTimeInterval;
34 @implementation iCalEvent
37 [self->endDate release];
38 [self->duration release];
39 [self->transparency release];
45 - (id)copyWithZone:(NSZone *)_zone {
48 new = [super copyWithZone:_zone];
50 ASSIGNCOPY(new->endDate, self->endDate);
51 ASSIGNCOPY(new->duration, self->duration);
52 ASSIGNCOPY(new->transparency, self->transparency);
59 - (void)setEndDate:(NSCalendarDate *)_date {
61 if (self->endDate == _date) return;
63 self->endDate = [_date retain];
66 - (NSCalendarDate *)endDate {
67 if ([self hasEndDate])
70 if ([self hasDuration] && (self->startDate != nil)) {
71 return [[self startDate] dateByAddingYears:0 months:0 days:0
73 seconds:[self durationAsTimeInterval]];
78 return self->endDate ? YES : NO;
81 - (void)setDuration:(NSString *)_value {
82 ASSIGNCOPY(self->duration, _value);
84 - (NSString *)duration {
85 // eg: "DURATION:PT1H"
86 if ([self hasDuration])
87 return self->duration;
93 return self->duration ? YES : NO;
95 - (NSTimeInterval)durationAsTimeInterval {
99 P2H30M - "2 hours 30 minutes"
101 dur-value = (["+"] / "-") "P" (dur-date / dur-time / dur-week)
103 dur-date = dur-day [dur-time]
104 dur-time = "T" (dur-hour / dur-minute / dur-second)
105 dur-week = 1*DIGIT "W"
106 dur-hour = 1*DIGIT "H" [dur-minute]
107 dur-minute = 1*DIGIT "M" [dur-second]
108 dur-second = 1*DIGIT "S"
109 dur-day = 1*DIGIT "D"
113 return [self->duration durationAsTimeInterval];
115 if (self->endDate != nil && self->startDate != nil)
116 /* calculate duration using enddate */
117 return [[self endDate] timeIntervalSinceDate:[self startDate]];
122 - (void)setTransparency:(NSString *)_transparency {
123 ASSIGNCOPY(self->transparency, _transparency);
125 - (NSString *)transparency {
126 return self->transparency;
134 s = [self transparency];
135 if (s && [[s uppercaseString] isEqualToString:@"TRANSPARENT"])
137 return YES; /* default is OPAQUE, see RFC2445, Section 4.8.2.7 */
141 The problem is, that startDate/endDate are inappropriately modelled here.
142 We'd need to have a special iCalDate in order to fix all the mess.
143 For the time being, we chose allday to mean 00:00 - 23:59 in startDate's
149 if (![self hasEndDate])
152 ed = [[[self endDate] copy] autorelease];
153 [ed setTimeZone:[self->startDate timeZone]];
154 if (([self->startDate hourOfDay] == 0) &&
155 ([self->startDate minuteOfHour] == 0) &&
156 ([ed hourOfDay] == 23) &&
157 ([ed minuteOfHour] == 59))
162 - (BOOL)isWithinCalendarDateRange:(NGCalendarDateRange *)_range {
163 if (![self isRecurrent]) {
164 if (self->startDate && self->endDate) {
165 NGCalendarDateRange *r;
167 r = [NGCalendarDateRange calendarDateRangeWithStartDate:self->startDate
168 endDate:self->endDate];
169 return [_range containsDateRange:r];
172 return [_range containsDate:self->startDate];
176 NGCalendarDateRange *fir;
178 fir = [NGCalendarDateRange calendarDateRangeWithStartDate:self->startDate
179 endDate:self->endDate];
181 return [self isWithinCalendarDateRange:_range
182 firstInstanceCalendarDateRange:fir];
187 - (NSArray *)recurrenceRangesWithinCalendarDateRange:(NGCalendarDateRange *)_r {
188 NGCalendarDateRange *fir;
190 if (![self isRecurrent])
193 fir = [NGCalendarDateRange calendarDateRangeWithStartDate:self->startDate
194 endDate:self->endDate];
195 return [self recurrenceRangesWithinCalendarDateRange:_r
196 firstInstanceCalendarDateRange:fir];
199 - (NSCalendarDate *)lastPossibleRecurrenceStartDate {
200 NGCalendarDateRange *fir;
202 if (![self isRecurrent])
205 fir = [NGCalendarDateRange calendarDateRangeWithStartDate:self->startDate
206 endDate:self->endDate];
207 return [self lastPossibleRecurrenceStartDateUsingFirstInstanceCalendarDateRange:fir];
212 - (NSString *)entityName {
218 - (NSString *)description {
221 ms = [NSMutableString stringWithCapacity:128];
222 [ms appendFormat:@"<0x%08X[%@]:", self, NSStringFromClass([self class])];
224 if (self->uid) [ms appendFormat:@" uid=%@", self->uid];
225 if (self->startDate) [ms appendFormat:@" from=%@", self->startDate];
226 if (self->endDate) [ms appendFormat:@" to=%@", self->endDate];
227 if (self->summary) [ms appendFormat:@" summary=%@", self->summary];
230 [ms appendFormat:@" organizer=%@", self->organizer];
232 [ms appendFormat:@" attendees=%@", self->attendees];
234 if ([self hasAlarms])
235 [ms appendFormat:@" alarms=%@", self->alarms];
237 [ms appendString:@">"];
243 - (iCalEventChanges *)getChangesRelativeToEvent:(iCalEvent *)_event {
244 return [iCalEventChanges changesFromEvent:_event
248 /* generating iCal content */
250 - (NSString *)vEventString {
251 return [[iCalRenderer sharedICalendarRenderer] vEventStringForEvent:self];
256 @implementation NSString(DurationTimeInterval)
258 - (NSTimeInterval)durationAsTimeInterval {
262 P2H30M - "2 hours 30 minutes"
264 dur-value = (["+"] / "-") "P" (dur-date / dur-time / dur-week)
266 dur-date = dur-day [dur-time]
267 dur-time = "T" (dur-hour / dur-minute / dur-second)
268 dur-week = 1*DIGIT "W"
269 dur-hour = 1*DIGIT "H" [dur-minute]
270 dur-minute = 1*DIGIT "M" [dur-second]
271 dur-second = 1*DIGIT "S"
272 dur-day = 1*DIGIT "D"
279 if (![self hasPrefix:@"P"]) {
280 NSLog(@"Cannot parse iCal duration value: '%@'", self);
286 for (i = 1, len = [self length], isTime = NO; i < len; i++) {
289 c = [self characterAtIndex:i];
290 if (c == 't' || c == 'T') {
297 val = (val * 10) + (c - 48);
303 ti += (val * 7 * 24 * 60 * 60);
306 ti += (val * 24 * 60 * 60);
309 ti += (val * 60 * 60);
318 [self logWithFormat:@"cannot process duration unit: '%c'", c];
326 @end /* NSString(DurationTimeInterval) */