]> err.no Git - sope/commitdiff
improved API, bugfix for recurrent dates
authorznek <znek@e4a50df8-12e2-0310-a44c-efbce7f8a7e3>
Tue, 1 Mar 2005 16:59:09 +0000 (16:59 +0000)
committerznek <znek@e4a50df8-12e2-0310-a44c-efbce7f8a7e3>
Tue, 1 Mar 2005 16:59:09 +0000 (16:59 +0000)
git-svn-id: http://svn.opengroupware.org/SOPE/trunk@603 e4a50df8-12e2-0310-a44c-efbce7f8a7e3

12 files changed:
sope-ical/NGiCal/ChangeLog
sope-ical/NGiCal/GNUmakefile
sope-ical/NGiCal/NGiCal.h
sope-ical/NGiCal/NGiCal.xcode/project.pbxproj
sope-ical/NGiCal/NSCalendarDate+ICal.h
sope-ical/NGiCal/NSCalendarDate+ICal.m
sope-ical/NGiCal/Version
sope-ical/NGiCal/iCalDateHolder.h
sope-ical/NGiCal/iCalRecurrenceCalculator.h
sope-ical/NGiCal/iCalRecurrenceCalculator.m
sope-ical/NGiCal/iCalRecurrenceRule.m
sope-ical/NGiCal/iCalRepeatableEntityObject.m

index 8eda6a0f9776a32038593a4e3ddc2c7fbf0f423f..7409c5ec965b5c8e696bfd24f10983a969306dc3 100644 (file)
@@ -1,3 +1,31 @@
+2005-02-28  Marcus Mueller  <znek@mulle-kybernetik.com>
+
+       * v4.5.47
+
+       * iCalRepeatableEntityObject.m:  shifted code to
+         iCalRecurrenceCalculator
+
+       * iCalRecurrenceCalculator.[hm]: new class method to calculate
+         complex recurrences. In SOGo this information is stored in quick
+         fields to reduce the complexity of lookups, hence we need to offer
+         a proper API to calculate date ranges from this information.
+         Fixed all calculations to explicitly set timeZone for all newly
+         created startDates - it seems the timeZone information is not
+         properly retained by the hour:minute:second: method from NGExtensions
+         which lead to improper DST related shifts.
+
+       * iCalDateHolder.h: exposed the API
+
+       * NSCalendarDate+ICal.[hm]: new convenience constructor for calendar
+         dates from iCal representations (uses iCalDateHolder internally)
+
+       * iCalRecurrenceRule.m: changed setUntil: to utilize new public
+         NSCalendarDate+ICal category
+
+       * NGiCal.h: added NSCalendarDate+ICal.h to the public headers
+
+       * GNUmakefile: NSCalendarDate+ICal.h is public now
+
 2005-02-20  Helge Hess  <helge.hess@opengroupware.org>
 
        * NGiCal.xmap: fixed a missing semicolon (did not load on MacOSX)
index 68633a8f8943ea3bcdc9a21f8fc1e4c5d692a715..403b98636315704d6c5044004b6d3a9e7acbaf87 100644 (file)
@@ -31,6 +31,8 @@ libNGiCal_HEADER_FILES =              \
        iCalRenderer.h                  \
        iCalRecurrenceRule.h            \
        iCalRecurrenceCalculator.h      \
+                                       \
+       NSCalendarDate+ICal.h           \
 
 #      IcalResponse.h                  \
 
index 55728e65da61ea225ee118ff3613164c1abe6521..a7ab997cd65939f3b2122090f2c5fc486050c462 100644 (file)
@@ -41,4 +41,6 @@
 #include <NGiCal/iCalRecurrenceRule.h>
 #include <NGiCal/iCalRecurrenceCalculator.h>
 
+#include <NGiCal/NSCalendarDate+ICal.h>
+
 #endif /* __NGiCal_H__ */
index 260e7a10a77d8edfc11ce3d2d8ce094146b93f7f..7bedbf0d9d31461ce17fd32a99a5d899e5856aad 100644 (file)
@@ -27,6 +27,9 @@
                        fileRef = AD770E6707AE627500F5C7A1;
                        isa = PBXBuildFile;
                        settings = {
+                               ATTRIBUTES = (
+                                       Public,
+                               );
                        };
                };
                AD770E6A07AE627500F5C7A1 = {
@@ -55,6 +58,9 @@
                        fileRef = AD77103C07AE8F8500F5C7A1;
                        isa = PBXBuildFile;
                        settings = {
+                               ATTRIBUTES = (
+                                       Public,
+                               );
                        };
                };
                AD77103F07AE8F8500F5C7A1 = {
                        fileRef = ADAACE6607B3973900FC48D6;
                        isa = PBXBuildFile;
                        settings = {
+                               ATTRIBUTES = (
+                                       Public,
+                               );
                        };
                };
                ADAACE6907B3973900FC48D6 = {
                        );
                        buildSettings = {
                                DYLIB_COMPATIBILITY_VERSION = 1;
-                               DYLIB_CURRENT_VERSION = 4.5.44;
+                               DYLIB_CURRENT_VERSION = 4.5.47;
                                FRAMEWORK_SEARCH_PATHS = "\"$(USER_LIBRARY_DIR)/EmbeddedFrameworks\"";
                                FRAMEWORK_VERSION = A;
                                GCC_PRECOMPILE_PREFIX_HEADER = NO;
                        );
                        buildSettings = {
                                DYLIB_COMPATIBILITY_VERSION = 1;
-                               DYLIB_CURRENT_VERSION = 4.5.44;
+                               DYLIB_CURRENT_VERSION = 4.5.47;
                                FRAMEWORK_SEARCH_PATHS = "$(LOCAL_LIBRARY_DIR)/Frameworks";
                                FRAMEWORK_VERSION = A;
                                GCC_PRECOMPILE_PREFIX_HEADER = YES;
                        isa = PBXBuildFile;
                        settings = {
                                ATTRIBUTES = (
+                                       Public,
                                );
                        };
                };
index 2af61b3f4649e5e0b95c018e933ee7997aaf763f..1f10eac24b126802f8da12f8f7dfe6f86075480a 100644 (file)
   02111-1307, USA.
 */
 
-#ifndef __ICal2_NSCalendarDate_ICal_H__
-#define __ICal2_NSCalendarDate_ICal_H__
+#ifndef __NGiCal_NSCalendarDate_ICal_H__
+#define __NGiCal_NSCalendarDate_ICal_H__
 
 #import <Foundation/NSCalendarDate.h>
 
 @class NSTimeZone;
 
-@interface NSCalendarDate(ICalValue)
+@interface NSCalendarDate(iCalRepresentation)
+
++ (id)calendarDateWithICalRepresentation:(NSString *)_iCalRep;
 
 /* represention */
 
@@ -41,4 +43,4 @@
 - (unsigned)daysBetweenDate:(NSCalendarDate *)_date;
 @end
 
-#endif /* __ICal2_NSCalendarDate_ICal_H__ */
+#endif /* __NGiCal_NSCalendarDate_ICal_H__ */
index 7a51986c9dfb65b581c913a666049660a557af9f..dd5b70a9ae7391f8659775dd19427e19585fa203 100644 (file)
@@ -20,6 +20,7 @@
 */
 
 #include "NSCalendarDate+ICal.h"
+#include "iCalDateHolder.h"
 #include "common.h"
 
 static NSTimeZone *gmt = nil;
@@ -28,12 +29,27 @@ static inline void _setupGMT(void) {
     gmt = [[NSTimeZone timeZoneWithAbbreviation:@"GMT"] retain];
 }
 
-@implementation NSCalendarDate(ICalValue)
+@interface iCalDateHolder (PrivateAPI)
+- (id)awakeAfterUsingSaxDecoder:(id)_decoder;
+@end
+
+@implementation NSCalendarDate(iCalRepresentation)
 
 /* represention */
 
 static NSString *gmtcalfmt = @"%Y%m%dT%H%M00Z";
 
++ (id)calendarDateWithICalRepresentation:(NSString *)_iCalRep {
+  iCalDateHolder *dh;
+  NSCalendarDate *date;
+  
+  dh = [[iCalDateHolder alloc] init];
+  [dh setString:_iCalRep];
+  date = [dh awakeAfterUsingSaxDecoder:nil];
+  [dh release];
+  return date;
+}
+
 - (NSString *)icalStringInGMT {
   NSTimeZone *oldtz;
   NSString   *s;
index bca2a88b74b31e484890424aedec47d87b34af4a..e3250f18100c991879c192fc41fc7f28d2e91c67 100644 (file)
@@ -2,7 +2,7 @@
 
 MAJOR_VERSION=4
 MINOR_VERSION=5
-SUBMINOR_VERSION:=46
+SUBMINOR_VERSION:=47
 
 # v4.5.40 requires NGExtensions v4.5.145
 # v4.5.37 requires NGExtensions v4.5.140
index 12927894166655bc1c21741c6f1e7fa2fed91aa9..fa6202730c6ff2cc77699b7c6bd5cfd180df790f 100644 (file)
@@ -24,7 +24,7 @@
 
 #import <Foundation/NSObject.h>
 
-@class NSString;
+@class NSString, NSTimeZone;
 
 @interface iCalDateHolder : NSObject
 {
   NSString *tag;
 }
 
+- (void)setString:(NSString *)_value;
+- (NSString *)string;
+
+- (void)setTag:(NSString *)_value;
+- (NSString *)tag;
+
+- (void)setTzid:(NSString *)_value;
+- (NSString *)tzid;
+
+- (NSTimeZone *)timeZone;
+
 @end
 
 #endif /* __NGiCal_iCalDateHolder_H__ */
index 661e91b6f239b7e8f4dd653d410bc7700219fa05..007a2ed86af91ee377187031f917759b4bae3edc 100644 (file)
   iCalRecurrenceRule  *rrule;
 }
 
++ (NSArray *)recurrenceRangesWithinCalendarDateRange:(NGCalendarDateRange *)_r
+  firstInstanceCalendarDateRange:(NGCalendarDateRange *)_fir
+  recurrenceRules:(NSArray *)_rRules
+  exceptionRules:(NSArray *)_exRules
+  exceptionDates:(NSArray *)_exDates;
+
 + (id)recurrenceCalculatorForRecurrenceRule:(iCalRecurrenceRule *)_rrule
   withFirstInstanceCalendarDateRange:(NGCalendarDateRange *)_range;
 
index 2931f5a67c8a944709b12b9f359069158c51c52b..d51e845a8b24d0056f46b3866a73ef77c1bc75e9 100644 (file)
@@ -61,6 +61,8 @@
 
 @implementation iCalRecurrenceCalculator
 
+static Class NSCalendarDateClass     = Nil;
+static Class iCalRecurrenceRuleClass = Nil;
 static Class dailyCalcClass   = Nil;
 static Class weeklyCalcClass  = Nil;
 static Class monthlyCalcClass = Nil;
@@ -72,12 +74,17 @@ static Class yearlyCalcClass  = Nil;
   if (didInit) return;
   didInit = YES;
 
+  NSCalendarDateClass     = [NSCalendarDate class];
+  iCalRecurrenceRuleClass = [iCalRecurrenceRule class];
+
   dailyCalcClass   = [iCalDailyRecurrenceCalculator   class];
   weeklyCalcClass  = [iCalWeeklyRecurrenceCalculator  class];
   monthlyCalcClass = [iCalMonthlyRecurrenceCalculator class];
   yearlyCalcClass  = [iCalYearlyRecurrenceCalculator  class];
 }
 
+/* factory */
+
 + (id)recurrenceCalculatorForRecurrenceRule:(iCalRecurrenceRule *)_rrule
          withFirstInstanceCalendarDateRange:(NGCalendarDateRange *)_range
 {
@@ -85,6 +92,80 @@ static Class yearlyCalcClass  = Nil;
                         firstInstanceCalendarDateRange:_range] autorelease];
 }
 
+/* complex calculation convenience */
+
++ (NSArray *)recurrenceRangesWithinCalendarDateRange:(NGCalendarDateRange *)_r
+  firstInstanceCalendarDateRange:(NGCalendarDateRange *)_fir
+  recurrenceRules:(NSArray *)_rRules
+  exceptionRules:(NSArray *)_exRules
+  exceptionDates:(NSArray *)_exDates
+{
+  id                       rule;
+  iCalRecurrenceCalculator *calc;
+  NSMutableArray           *ranges;
+  unsigned                 i, count, rCount;
+  
+  ranges = [NSMutableArray array];
+  count  = [_rRules count];
+  for (i = 0; i < count; i++) {
+    NSArray *rs;
+
+    rule = [_rRules objectAtIndex:i];
+    if (![rule isKindOfClass:iCalRecurrenceRuleClass])
+      rule = [iCalRecurrenceRule recurrenceRuleWithICalRepresentation:rule];
+  
+    calc = [self recurrenceCalculatorForRecurrenceRule:rule
+                 withFirstInstanceCalendarDateRange:_fir];
+    rs   = [calc recurrenceRangesWithinCalendarDateRange:_r];
+    [ranges addObjectsFromArray:rs];
+  }
+  
+  if (![ranges count])
+    return nil;
+  
+  /* test if any exceptions do match */
+  count = [_exRules count];
+  for (i = 0; i < count; i++) {
+    NSArray *rs;
+
+    rule = [_exRules objectAtIndex:i];
+    if (![rule isKindOfClass:iCalRecurrenceRuleClass])
+      rule = [iCalRecurrenceRule recurrenceRuleWithICalRepresentation:rule];
+
+    calc = [self recurrenceCalculatorForRecurrenceRule:rule
+                 withFirstInstanceCalendarDateRange:_fir];
+    rs   = [calc recurrenceRangesWithinCalendarDateRange:_r];
+    [ranges removeObjectsInArray:rs];
+  }
+  
+  if (![ranges count])
+    return nil;
+  
+  /* exception dates are also possible */
+  rCount = [ranges count];
+  count  = [_exDates count];
+  for (i = 0; i < count; i++) {
+    id                  exDate;
+    NGCalendarDateRange *r;
+    unsigned            k;
+
+    exDate = [_exDates objectAtIndex:i];
+    if (![exDate isKindOfClass:NSCalendarDateClass]) {
+      exDate = [NSCalendarDate calendarDateWithICalRepresentation:exDate];
+    }
+    for (k = 0; k < rCount; k++) {
+      r = [ranges objectAtIndex:(rCount - k) - 1];
+      if ([r containsDate:exDate]) {
+        [ranges removeObjectAtIndex:k];
+      }
+    }
+  }
+  return ranges;
+}
+
+
+/* init */
+
 - (id)initWithRecurrenceRule:(iCalRecurrenceRule *)_rrule
   firstInstanceCalendarDateRange:(NGCalendarDateRange *)_range
 {
@@ -252,6 +333,7 @@ static Class yearlyCalcClass  = Nil;
         NGCalendarDateRange *r;
       
         start = [NSCalendarDate dateForJulianNumber:jnCurrent];
+        [start setTimeZone:[firStart timeZone]];
         start = [start hour:  [firStart hourOfDay]
                        minute:[firStart minuteOfHour]
                        second:[firStart secondOfMinute]];
@@ -348,6 +430,7 @@ static Class yearlyCalcClass  = Nil;
           NGCalendarDateRange *r;
           
           start = [NSCalendarDate dateForJulianNumber:jnCurrent];
+          [start setTimeZone:[firStart timeZone]];
           start = [start hour:  [firStart hourOfDay]
                          minute:[firStart minuteOfHour]
                          second:[firStart secondOfMinute]];
@@ -395,6 +478,7 @@ static Class yearlyCalcClass  = Nil;
             NGCalendarDateRange *r;
                 
             start = [NSCalendarDate dateForJulianNumber:jnCurrent];
+            [start setTimeZone:[firStart timeZone]];
             start = [start hour:  [firStart hourOfDay]
                            minute:[firStart minuteOfHour]
                            second:[firStart secondOfMinute]];
@@ -465,6 +549,7 @@ static Class yearlyCalcClass  = Nil;
       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];
@@ -525,6 +610,7 @@ static Class yearlyCalcClass  = Nil;
       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];
index 7c09525fdb2c23aff6bae64b52323d39cae033bf..a502ed9d815ef4ecaa6af8795b5f8a8ccea743f4 100644 (file)
@@ -20,7 +20,6 @@
 */
 
 #include "iCalRecurrenceRule.h"
-#include "iCalDateHolder.h"
 #include "NSCalendarDate+ICal.h"
 #include "common.h"
 
  wkst       = rrWeekStart;
  */
 
-@interface iCalDateHolder (PrivateAPI)
-- (void)setString:(NSString *)_value;
-- (id)awakeAfterUsingSaxDecoder:(id)_decoder;
-@end
-
 @interface iCalRecurrenceRule (PrivateAPI)
 - (iCalWeekDay)weekDayFromICalRepresentation:(NSString *)_day;
 - (NSString *)iCalRepresentationForWeekDay:(iCalWeekDay)_weekDay;
   self->repeatCount = [_count unsignedIntValue];
 }
 - (void)setUntil:(NSString *)_until {
-  iCalDateHolder *dh;
   NSCalendarDate *date;
 
-  dh = [[iCalDateHolder alloc] init];
-  [dh setString:_until];
-  date = [dh awakeAfterUsingSaxDecoder:nil];
+  date = [NSCalendarDate calendarDateWithICalRepresentation:_until];
   ASSIGN(self->untilDate, date);
-  [dh release];
 }
 
 - (void)setWkst:(NSString *)_weekStart {
index 48ab00cc2f102f49d1f05d4555608fb19ab5469a..6d9a0ea8743e72cb11efcee70f60102c52eaaefd 100644 (file)
 - (NSArray *)recurrenceRangesWithinCalendarDateRange:(NGCalendarDateRange *)_r
   firstInstanceCalendarDateRange:(NGCalendarDateRange *)_fir
 {
-  iCalRecurrenceRule       *rule;
-  iCalRecurrenceCalculator *calc;
-  NSMutableArray           *ranges;
-  unsigned                 i, count, rCount;
-
-  ranges = [NSMutableArray array];
-  count  = [self->rRules count];
-  for (i = 0; i < count; i++) {
-    NSArray *rs;
-
-    rule = [self->rRules objectAtIndex:i];
-    calc = [iCalRecurrenceCalculator recurrenceCalculatorForRecurrenceRule:rule
-                                     withFirstInstanceCalendarDateRange:_fir];
-    rs   = [calc recurrenceRangesWithinCalendarDateRange:_r];
-    [ranges addObjectsFromArray:rs];
-  }
-  
-  if (![ranges count])
-    return nil;
-
-  /* test if any exceptions do match */
-  count = [self->exRules count];
-  for (i = 0; i < count; i++) {
-    NSArray *rs;
-
-    rule = [self->exRules objectAtIndex:i];
-    calc = [iCalRecurrenceCalculator recurrenceCalculatorForRecurrenceRule:rule
-                                     withFirstInstanceCalendarDateRange:_fir];
-    rs   = [calc recurrenceRangesWithinCalendarDateRange:_r];
-    [ranges removeObjectsInArray:rs];
-  }
-
-  if (![ranges count])
-    return nil;
-
-  /* exception dates are also possible */
-  rCount = [ranges count];
-  count  = [self->exDates count];
-  for (i = 0; i < count; i++) {
-    NSCalendarDate      *exDate;
-    NGCalendarDateRange *r;
-    unsigned            k;
-
-    exDate = [self->exDates objectAtIndex:i];
-    for (k = 0; k < rCount; k++) {
-      r = [ranges objectAtIndex:(rCount - k) - 1];
-      if ([r containsDate:exDate]) {
-        [ranges removeObjectAtIndex:k];
-      }
-    }
-  }
-  return ranges;
+  return [iCalRecurrenceCalculator recurrenceRangesWithinCalendarDateRange:_r
+                                   firstInstanceCalendarDateRange:_fir
+                                   recurrenceRules:self->rRules
+                                   exceptionRules:self->exRules
+                                   exceptionDates:self->exDates];
 }