See Changelog.

Monotone-Parent: 8f58a8aa696d8fbbb82f1cd571800676a04b96af
Monotone-Revision: b593ce96638476fad98d678453ca6af6112169fb

Monotone-Author: flachapelle@inverse.ca
Monotone-Date: 2011-01-14T02:54:33
Monotone-Branch: ca.inverse.sogo
maint-2.0.2
Francis Lachapelle 2011-01-14 02:54:33 +00:00
parent b6bc06b163
commit 64081b8fa7
13 changed files with 259 additions and 137 deletions

View File

@ -1,3 +1,26 @@
2011-01-13 Francis Lachapelle <flachapelle@inverse.ca>
* SoObjects/Appointments/iCalRepeatableEntityObject+SOGo.m
(-doesOccurOnDate:): the date to verify must be adjusted to the
event's timezone before performing the calculation of the
recurrence rule.
* SoObjects/Appointments/iCalEvent+SOGo.m (-firstOccurenceRange):
extract the original start and end dates from the event, based on
the event's timezone.
* SoObjects/Appointments/SOGoAppointmentFolder.m
(-fixupCycleRecord:cycleRange:firstInstanceCalendarDateRange:withEventTimeZone:):
the event dates must be first be adjusted to the event's timezone
before being adjusted to the user's timezone.
(-_flattenCycleRecord:forRange:intoArray:): the calculation of the
occurrences must be performed with respect to the event's
timezone, not the user's timezone.
* SoObjects/Appointments/SOGoAppointmentObject.m
(-newOccurenceWithID:): new occurrences are now independant of the
user's timezone.
2011-01-11 Ludovic Marcotte <lmarcotte@inverse.ca>
* OpenChange/MAPIStoreContactsMessageTable.m

View File

@ -1,3 +1,13 @@
2011-01-13 Francis Lachapelle <flachapelle@inverse.ca>
* iCalTimeZone.m (-computedDateForDate:): Was
_computedDateTimeForDate. Adjusts a date with respect to this
vTimeZone.
* iCalDateTime.m (-dateTimes): when there's no timezone defined
(which is the case when parsing a vTimeZone!), don't fallback to
the system timezone.
2010-11-18 Wolfgang Sourdeau <wsourdeau@inverse.ca>
* NGVCard.m (-setVName, vName): removed useless and non-standard

View File

@ -161,6 +161,7 @@
currentEndDate = [currentStartDate addTimeInterval: [firstRange duration]];
r = [NGCalendarDateRange calendarDateRangeWithStartDate: currentStartDate
endDate: currentEndDate];
if ([_r containsDateRange: r])
[ranges addObject: r];
}

View File

@ -1,6 +1,6 @@
/* iCalDateTime.m - this file is part of SOPE
*
* Copyright (C) 2006 Inverse inc.
* Copyright (C) 2006-2011 Inverse inc.
*
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
*
@ -161,7 +161,7 @@
NSString *date;
NSCalendarDate *initialDate, *dateTime;
NSMutableArray *dates;
NSTimeZone *tz;
//NSTimeZone *tz;
unsigned count, i;
count = [[self values] count];
@ -170,24 +170,28 @@
{
date = [self value: i];
iTZ = [self timeZone];
if (iTZ)
dateTime = [iTZ dateForDateTimeString: date];
else
{
initialDate = [date asCalendarDate];
if (initialDate)
dateTime = initialDate;
/*
{
if ([date hasSuffix: @"Z"] || [date hasSuffix: @"z"])
dateTime = initialDate;
else
{
/* same TODO as above */
// same TODO as above
tz = [NSTimeZone defaultTimeZone];
dateTime = [initialDate addYear: 0 month: 0 day: 0
hour: 0 minute: 0
second: -[tz secondsFromGMTForDate: initialDate]];
}
}
*/
else
dateTime = nil;
}

View File

@ -1,6 +1,6 @@
/* iCalTimeZone.h - this file is part of SOPE
*
* Copyright (C) 2006-2009 Inverse inc.
* Copyright (C) 2006-2011 Inverse inc.
*
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
*
@ -28,10 +28,14 @@
#import "CardGroup.h"
@class iCalTimeZonePeriod;
@interface iCalTimeZone : CardGroup
+ (iCalTimeZone *) timeZoneForName: (NSString *) theName;
- (NSString *) tzId;
- (iCalTimeZonePeriod *) periodForDate: (NSCalendarDate *) date;
- (NSCalendarDate *) computedDateForDate: (NSCalendarDate *) theDate;
- (NSString *) dateTimeStringForDate: (NSCalendarDate *) date;
- (NSString *) dateStringForDate: (NSCalendarDate *) date;
- (NSCalendarDate *) dateForDateTimeString: (NSString *) string;

View File

@ -1,9 +1,10 @@
/* iCalTimeZone.m - this file is part of SOPE
*
* Copyright (C) 2006-2009 Inverse inc.
* Copyright (C) 2006-2011 Inverse inc.
*
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
* Ludovic Marcotte <lmarcotte@inverse.ca>
* Francis Lachapelle <flachapelle@inverse.ca>
*
* This file is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -185,35 +186,38 @@ static NSMutableDictionary *cache;
period = (iCalTimeZonePeriod *) [self uniqueChildWithTag: @"daylight"];
}
// NSLog (@"chosen period: '%@'", [period tag]);
return period;
}
- (NSCalendarDate *) _computedDateTimeForDate: (NSCalendarDate *) date
/**
* Adjust a date with respect to this vTimeZone.
* @param theDate the date to adjust to the timezone.
* @return a new GMT date adjusted with the offset of the timezone.
*/
- (NSCalendarDate *) computedDateForDate: (NSCalendarDate *) theDate
{
NSCalendarDate *tmpDate;
NSTimeZone *utc;
utc = [NSTimeZone timeZoneWithName: @"GMT"];
tmpDate = [date copy];
tmpDate = [theDate copy];
[tmpDate autorelease];
[tmpDate setTimeZone: utc];
return [tmpDate addYear: 0 month: 0 day: 0
hour: 0 minute: 0
second: [[self periodForDate: date] secondsOffsetFromGMT]];
second: [[self periodForDate: theDate] secondsOffsetFromGMT]];
}
- (NSString *) dateTimeStringForDate: (NSCalendarDate *) date
{
return [[self _computedDateTimeForDate: date]
return [[self computedDateForDate: date]
iCalFormattedDateTimeString];
}
- (NSString *) dateStringForDate: (NSCalendarDate *) date
{
return [[self _computedDateTimeForDate: date]
return [[self computedDateForDate: date]
iCalFormattedDateString];
}

View File

@ -137,6 +137,7 @@
}
tzStart = [self startDate];
[tzStart setTimeZone: [NSTimeZone timeZoneWithName: @"GMT"]];
tmpDate = [NSCalendarDate dateWithYear: [refDate yearOfCommonEra]
month: [[rrule namedValue: @"bymonth"] intValue]

View File

@ -186,6 +186,7 @@
currentEndDate = [currentStartDate addTimeInterval: [firstRange duration]];
r = [NGCalendarDateRange calendarDateRangeWithStartDate: currentStartDate
endDate: currentEndDate];
if ([_r containsDateRange: r])
[ranges addObject: r];
}

View File

@ -1,5 +1,5 @@
/*
Copyright (C) 2007-2009 Inverse inc.
Copyright (C) 2007-2011 Inverse inc.
Copyright (C) 2004-2005 SKYRIX Software AG
This file is part of OpenGroupware.org.
@ -46,6 +46,7 @@
#import <NGCards/iCalPerson.h>
#import <NGCards/iCalRecurrenceCalculator.h>
#import <NGCards/iCalTimeZone.h>
#import <NGCards/iCalTimeZonePeriod.h>
#import <NGCards/NSString+NGCards.h>
#import <NGExtensions/NGCalendarDateRange.h>
#import <NGExtensions/NSNull+misc.h>
@ -576,33 +577,38 @@ static NSNumber *sharedYes = nil;
forKey: [currentRecord objectForKey: @"c_name"]];
}
- (NSMutableDictionary *) fixupRecord: (NSDictionary *) _record
/**
* Set the timezone of the event start and end dates to the user's timezone.
* @param theRecord an dictionnary with the attributes of the event.
* @return a copy of theRecord with adjusted dates.
*/
- (NSMutableDictionary *) fixupRecord: (NSDictionary *) theRecord
{
NSMutableDictionary *md;
NSMutableDictionary *record;
static NSString *fields[] = { @"c_startdate", @"startDate",
@"c_enddate", @"endDate" };
unsigned int count;
NSCalendarDate *date;
NSNumber *dateValue;
md = [[_record mutableCopy] autorelease];
record = [[theRecord mutableCopy] autorelease];
for (count = 0; count < 2; count++)
{
dateValue = [_record objectForKey: fields[count * 2]];
dateValue = [theRecord objectForKey: fields[count * 2]];
if (dateValue)
{
date = [NSCalendarDate dateWithTimeIntervalSince1970: [dateValue unsignedIntValue]];
if (date)
{
[date setTimeZone: timeZone];
[md setObject: date forKey: fields[count * 2 + 1]];
[record setObject: date forKey: fields[count * 2 + 1]];
}
}
else
[self logWithFormat: @"missing '%@' in record?", fields[count * 2]];
}
return md;
return record;
}
- (NSArray *) fixupRecords: (NSArray *) theRecords
@ -629,42 +635,52 @@ static NSNumber *sharedYes = nil;
return ma;
}
- (NSMutableDictionary *) fixupCycleRecord: (NSDictionary *) _record
cycleRange: (NGCalendarDateRange *) _r
firstInstanceCalendarDateRange: (NGCalendarDateRange *) _fir
forViewRange: (NGCalendarDateRange *) _viewRange
/**
* Adjust the timezone of the start and end dates to the user's timezone.
* The event is recurrent and the dates must first be adjusted with respect to
* the event's timezone.
* @param theRecord
* @param theCycle
* @param theFirstCycle
* @param theEventTimeZone
* @see fixupRecord:
* @return a copy of theRecord with adjusted dates.
*/
- (NSMutableDictionary *) fixupCycleRecord: (NSDictionary *) theRecord
cycleRange: (NGCalendarDateRange *) theCycle
firstInstanceCalendarDateRange: (NGCalendarDateRange *) theFirstCycle
withEventTimeZone: (iCalTimeZone *) theEventTimeZone
{
NSMutableDictionary *md;
NSMutableDictionary *record;
NSNumber *dateSecs;
id tmp;
md = [[_record mutableCopy] autorelease];
id date;
int secondsOffsetFromGMT;
/* cycle is in _r. We also have to override the c_startdate/c_enddate with the date values of
the reccurence since we use those when displaying events in SOGo Web */
record = [[theRecord mutableCopy] autorelease];
tmp = [_r startDate];
[tmp setTimeZone: timeZone];
[md setObject: tmp forKey: @"startDate"];
dateSecs = [NSNumber numberWithInt: [tmp timeIntervalSince1970]];
[md setObject: dateSecs forKey: @"c_startdate"];
date = [theCycle startDate];
secondsOffsetFromGMT = (int) [[theEventTimeZone periodForDate: date] secondsOffsetFromGMT];
date = [date dateByAddingYears: 0 months: 0 days: 0 hours: 0 minutes: 0 seconds: -secondsOffsetFromGMT];
[date setTimeZone: timeZone];
[record setObject: date forKey: @"startDate"];
dateSecs = [NSNumber numberWithInt: [date timeIntervalSince1970]];
[record setObject: dateSecs forKey: @"c_startdate"];
[record setObject: dateSecs forKey: @"c_recurrence_id"];
tmp = [_r endDate];
[tmp setTimeZone: timeZone];
[md setObject: tmp forKey: @"endDate"];
dateSecs = [NSNumber numberWithInt: [tmp timeIntervalSince1970]];
[md setObject: dateSecs forKey: @"c_enddate"];
tmp = [_r startDate];
dateSecs = [NSNumber numberWithInt: [tmp timeIntervalSince1970]];
[md setObject: dateSecs forKey: @"c_recurrence_id"];
date = [theCycle endDate];
secondsOffsetFromGMT = (int) [[theEventTimeZone periodForDate: date] secondsOffsetFromGMT];
date = [date dateByAddingYears: 0 months: 0 days: 0 hours: 0 minutes: 0 seconds: -secondsOffsetFromGMT];
[date setTimeZone: timeZone];
[record setObject: date forKey: @"endDate"];
dateSecs = [NSNumber numberWithInt: [date timeIntervalSince1970]];
[record setObject: dateSecs forKey: @"c_enddate"];
// The first instance date is added to the dictionary so it can
// be used by UIxCalListingActions to compute the DST offset.
tmp = [_fir startDate];
[md setObject: tmp forKey: @"cycleStartDate"];
date = [theFirstCycle startDate];
[record setObject: date forKey: @"cycleStartDate"];
return md;
return record;
}
- (int) _indexOfRecordMatchingDate: (NSCalendarDate *) matchDate
@ -805,26 +821,39 @@ firstInstanceCalendarDateRange: (NGCalendarDateRange *) fir
}
}
- (void) _flattenCycleRecord: (NSDictionary *) _row
forRange: (NGCalendarDateRange *) _r
intoArray: (NSMutableArray *) _ma
/**
* Calculate and return the occurrences of the recurrent event for the given
* period.
* @param theRecord the event definition.
* @param theRange the period to look in.
* @param theRecords the array into which are copied the resulting occurrences.
*/
- (void) _flattenCycleRecord: (NSDictionary *) theRecord
forRange: (NGCalendarDateRange *) theRange
intoArray: (NSMutableArray *) theRecords
{
NSMutableDictionary *row, *fixedRow;
NSMutableArray *recordArray;
NSDictionary *cycleinfo;
NSCalendarDate *startDate, *endDate;
NGCalendarDateRange *fir, *rRange;
NSArray *rules, *exRules, *exDates, *ranges;
unsigned i, count;
NSMutableArray *records;
NSDictionary *cycleinfo;
NSCalendarDate *startDate, *endDate;
NGCalendarDateRange *firstRange, *oneRange;
NSArray *rules, *exRules, *exDates, *ranges;
NSArray *elements, *components;
NSString *content;
iCalRepeatableEntityObject *component;
iCalDateTime *firstStartDate, *firstEndDate;
NSCalendarDate *checkStartDate, *checkEndDate;
iCalTimeZone *eventTimeZone;
unsigned i, count;
recordArray = [NSMutableArray array];
records = [NSMutableArray array];
ranges = nil;
content = [_row objectForKey: @"c_cycleinfo"];
content = [theRecord objectForKey: @"c_cycleinfo"];
if (![content isNotNull])
{
[self errorWithFormat:@"cyclic record doesn't have cycleinfo -> %@",
_row];
theRecord];
return;
}
@ -832,45 +861,72 @@ firstInstanceCalendarDateRange: (NGCalendarDateRange *) fir
if (!cycleinfo)
{
[self errorWithFormat:@"cyclic record doesn't have cycleinfo -> %@",
_row];
theRecord];
return;
}
row = [self fixupRecord: _row];
row = [self fixupRecord: theRecord];
[row removeObjectForKey: @"c_cycleinfo"];
[row setObject: sharedYes forKey: @"isRecurrentEvent"];
startDate = [row objectForKey: @"startDate"];
endDate = [row objectForKey: @"endDate"];
fir = [NGCalendarDateRange calendarDateRangeWithStartDate: startDate
endDate: endDate];
rules = [cycleinfo objectForKey: @"rules"];
exRules = [cycleinfo objectForKey: @"exRules"];
exDates = [cycleinfo objectForKey: @"exDates"];
ranges = [iCalRecurrenceCalculator recurrenceRangesWithinCalendarDateRange: _r
firstInstanceCalendarDateRange: fir
recurrenceRules: rules
exceptionRules: exRules
exceptionDates: exDates];
content = [theRecord objectForKey: @"c_content"];
if ([content length])
{
elements = [iCalCalendar parseFromSource: content];
if ([elements count])
{
components = [[elements objectAtIndex: 0] events];
if ([components count])
{
// Retrieve the range of the first event
component = [components objectAtIndex: 0];
firstStartDate = (iCalDateTime*)[component uniqueChildWithTag: @"dtstart"];
firstEndDate = (iCalDateTime*)[component uniqueChildWithTag: @"dtend"];
eventTimeZone = [firstStartDate timeZone];
startDate = [eventTimeZone computedDateForDate: startDate];
firstRange = [NGCalendarDateRange calendarDateRangeWithStartDate: [[[firstStartDate values] lastObject] asCalendarDate]
endDate: [[[firstEndDate values] lastObject] asCalendarDate]];
// Adjust the range to check with respect to the event timezone (extracted from the start date)
checkStartDate = [eventTimeZone computedDateForDate: [theRange startDate]];
checkEndDate = [eventTimeZone computedDateForDate: [theRange endDate]];
theRange = [NGCalendarDateRange calendarDateRangeWithStartDate: checkStartDate
endDate: checkEndDate];
// Calculate the occurrences for the given range
rules = [cycleinfo objectForKey: @"rules"];
exRules = [cycleinfo objectForKey: @"exRules"];
exDates = [cycleinfo objectForKey: @"exDates"];
ranges = [iCalRecurrenceCalculator recurrenceRangesWithinCalendarDateRange: theRange
firstInstanceCalendarDateRange: firstRange
recurrenceRules: rules
exceptionRules: exRules
exceptionDates: exDates];
}
}
}
count = [ranges count];
for (i = 0; i < count; i++)
{
rRange = [ranges objectAtIndex: i];
fixedRow = [self fixupCycleRecord: row
cycleRange: rRange
firstInstanceCalendarDateRange: fir
forViewRange: _r];
oneRange = [ranges objectAtIndex: i];
fixedRow = [self fixupCycleRecord: row
cycleRange: oneRange
firstInstanceCalendarDateRange: firstRange
withEventTimeZone: eventTimeZone];
if (fixedRow)
[recordArray addObject: fixedRow];
[records addObject: fixedRow];
}
[self _appendCycleExceptionsFromRow: row
firstInstanceCalendarDateRange: fir
forRange: _r
toArray: recordArray];
firstInstanceCalendarDateRange: firstRange
forRange: theRange
toArray: records];
[_ma addObjectsFromArray: recordArray];
[theRecords addObjectsFromArray: records];
}
- (NSArray *) _flattenCycleRecords: (NSArray *) _records

View File

@ -1,6 +1,6 @@
/*
Copyright (C) 2007-2011 Inverse inc.
Copyright (C) 2004-2005 SKYRIX Software AG
Copyright (C) 2007-2009 Inverse inc.
This file is part of OpenGroupware.org.
@ -80,33 +80,28 @@
inContainer: self];
}
- (iCalRepeatableEntityObject *) newOccurenceWithID: (NSString *) recID
/**
* Return a new exception in a the recurrent event.
* @param theRecurrenceID the ID of the occurence.
* @return a new occurence.
*/
- (iCalRepeatableEntityObject *) newOccurenceWithID: (NSString *) theRecurrenceID
{
iCalEvent *newOccurence, *master;
NSCalendarDate *date, *firstDate;
unsigned int interval, nbrDays;
SOGoUserDefaults *ud;
NSTimeZone *timeZone;
int daylightOffset;
ud = [[SOGoUser userWithLogin: owner] userDefaults];
timeZone = [ud timeZone];
newOccurence = (iCalEvent *) [super newOccurenceWithID: recID];
newOccurence = (iCalEvent *) [super newOccurenceWithID: theRecurrenceID];
date = [newOccurence recurrenceId];
master = [self component: NO secure: NO];
firstDate = [master startDate];
// We are creating a new exception in a recurrent event -- compute the daylight
// saving time with respect to the first occurrence of the recurrent event.
daylightOffset = (int) ([timeZone secondsFromGMTForDate: firstDate]
- [timeZone secondsFromGMTForDate: date]);
if (daylightOffset)
date = [date dateByAddingYears: 0 months: 0 days: 0
hours:0 minutes: 0 seconds: daylightOffset];
[date setTimeZone: timeZone];
interval = [[master endDate]
timeIntervalSinceDate: firstDate];
if ([newOccurence isAllDay])

View File

@ -1,8 +1,9 @@
/* iCalEvent+SOGo.m - this file is part of SOGo
*
* Copyright (C) 2007 Inverse inc.
* Copyright (C) 2007-2011 Inverse inc.
*
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
* Francis Lachapelle <flachapelle@inverse.ca>
*
* This file is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -30,6 +31,7 @@
#import <NGExtensions/NSObject+Logs.h>
#import <NGCards/iCalAlarm.h>
#import <NGCards/iCalDateTime.h>
#import <NGCards/iCalEvent.h>
#import <NGCards/iCalPerson.h>
#import <NGCards/iCalTrigger.h>
@ -240,10 +242,22 @@
return row;
}
/**
* Extract the start and end dates from the event, from which all recurrence
* calculations will be based on.
* @return the range of the first occurrence.
*/
- (NGCalendarDateRange *) firstOccurenceRange
{
return [NGCalendarDateRange calendarDateRangeWithStartDate: [self startDate]
endDate: [self endDate]];
iCalDateTime *firstStartDate, *firstEndDate;
NGCalendarDateRange *firstRange;
firstStartDate = (iCalDateTime *)[self uniqueChildWithTag: @"dtstart"];
firstEndDate = (iCalDateTime *)[self uniqueChildWithTag: @"dtend"];
firstRange = [NGCalendarDateRange calendarDateRangeWithStartDate: [[[firstStartDate values] lastObject] asCalendarDate]
endDate: [[[firstEndDate values] lastObject] asCalendarDate]];
return firstRange;
}
- (unsigned int) occurenceInterval

View File

@ -1,6 +1,6 @@
/* iCalRepeatableEntityObject+SOGo.m - this file is part of SOGo
/*
Copyright (C) 2008-2011 Inverse inc.
Copyright (C) 2004-2005 SKYRIX Software AG
Copyright (C) 2008 Inverse inc.
This file is part of OpenGroupware.org.
@ -26,8 +26,11 @@
#import <Foundation/NSString.h>
#import <Foundation/NSTimeZone.h>
#import <NGCards/iCalDateTime.h>
#import <NGCards/iCalRecurrenceRule.h>
#import <NGCards/iCalRecurrenceCalculator.h>
#import <NGCards/iCalTimeZone.h>
#import <NGCards/NSString+NGCards.h>
#import <NGExtensions/NGCalendarDateRange.h>
#import "iCalRepeatableEntityObject+SOGo.h"
@ -104,25 +107,39 @@
return 0;
}
- (BOOL) doesOccurOnDate: (NSCalendarDate *) occurenceDate
/**
* Checks if a date is part of the recurring entity.
* @param theOccurrenceDate the date to verify.
* @return true if the occurence date is part of the recurring entity.
*/
- (BOOL) doesOccurOnDate: (NSCalendarDate *) theOccurenceDate
{
NSArray *ranges;
NGCalendarDateRange *checkRange;
NSCalendarDate *endDate;
NGCalendarDateRange *checkRange, *firstRange;
NSCalendarDate *startDate, *endDate;
iCalDateTime *firstStartDate;
BOOL doesOccur;
doesOccur = [self isRecurrent];
if (doesOccur)
{
endDate = [occurenceDate addTimeInterval: [self occurenceInterval]];
checkRange = [NGCalendarDateRange calendarDateRangeWithStartDate: occurenceDate
endDate: endDate];
// Retrieve the range of the first event
firstRange = [self firstOccurenceRange];
// Set the range to check with respect to the event timezone (extracted from the start date)
firstStartDate = (iCalDateTime *)[self uniqueChildWithTag: @"dtstart"];
startDate = [[firstStartDate timeZone] computedDateForDate: theOccurenceDate];
endDate = [startDate addTimeInterval: [self occurenceInterval]];
checkRange = [NGCalendarDateRange calendarDateRangeWithStartDate: startDate
endDate: endDate];
// Calculate the occurrences for the given date
ranges = [iCalRecurrenceCalculator recurrenceRangesWithinCalendarDateRange: checkRange
firstInstanceCalendarDateRange: [self firstOccurenceRange]
recurrenceRules: [self recurrenceRules]
exceptionRules: [self exceptionRules]
exceptionDates: [self exceptionDates]];
doesOccur = [ranges dateRangeArrayContainsDate: occurenceDate];
firstInstanceCalendarDateRange: firstRange
recurrenceRules: [self recurrenceRules]
exceptionRules: [self exceptionRules]
exceptionDates: [self exceptionDates]];
doesOccur = [ranges dateRangeArrayContainsDate: startDate];
}
return doesOccur;

View File

@ -1,8 +1,9 @@
/* UIxCalListingActions.m - this file is part of SOGo
*
* Copyright (C) 2006-2010 Inverse inc.
* Copyright (C) 2006-2011 Inverse inc.
*
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
* Francis Lachapelle <flachapelle@inverse.ca>
*
* This file is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -34,6 +35,8 @@
#import <NGObjWeb/WOResponse.h>
#import <NGCards/iCalPerson.h>
#import <NGCards/iCalTimeZone.h>
#import <NGCards/iCalDateTime.h>
#import <NGExtensions/NGCalendarDateRange.h>
#import <NGExtensions/NSCalendarDate+misc.h>
@ -246,8 +249,12 @@ static NSArray *tasksFields = nil;
forKey: @"c_title"];
}
/* TODO: shouldn't this be handled when creating the quick records ? */
- (void) _fixDates: (NSMutableDictionary *) aRecord
/*
* Adjust the event start and end dates when there's a time change
* in the period covering the view for the user's timezone.
* @param theRecord the attributes of the event.
*/
- (void) _fixDates: (NSMutableDictionary *) theRecord
{
NSCalendarDate *aDate, *aStartDate;
NSNumber *aDateValue;
@ -272,41 +279,25 @@ static NSArray *tasksFields = nil;
http://www.sogo.nu/bugs/view.php?id=678
...
*/
if (dayBasedView || [[aRecord objectForKey: @"c_isallday"] boolValue])
if (dayBasedView || [[theRecord objectForKey: @"c_isallday"] boolValue])
{
for (count = 0; count < 2; count++)
{
aDateField = fields[count * 2];
aDate = [aRecord objectForKey: aDateField];
daylightOffset = (int) ([userTimeZone secondsFromGMTForDate: aDate]
- [userTimeZone secondsFromGMTForDate: startDate]);
aDate = [theRecord objectForKey: aDateField];
daylightOffset = (int) ([userTimeZone secondsFromGMTForDate: aDate]
- [userTimeZone secondsFromGMTForDate: startDate]);
if (daylightOffset)
{
aDate = [aDate dateByAddingYears: 0 months: 0 days: 0 hours: 0
minutes: 0 seconds: daylightOffset];
[aRecord setObject: aDate forKey: aDateField];
[theRecord setObject: aDate forKey: aDateField];
aDateValue = [NSNumber numberWithInt: [aDate timeIntervalSince1970]];
[aRecord setObject: aDateValue forKey: fields[count * 2 + 1]];
[theRecord setObject: aDateValue forKey: fields[count * 2 + 1]];
}
}
}
aDateValue = [aRecord objectForKey: @"c_recurrence_id"];
aDate = [aRecord objectForKey: @"cycleStartDate"];
if (aDateValue && aDate)
{
aStartDate = [aRecord objectForKey: @"startDate"];
if ([userTimeZone isDaylightSavingTimeForDate: aStartDate] !=
[userTimeZone isDaylightSavingTimeForDate: aDate])
{
// For the event's recurrence id, compute the daylight saving time
// offset with respect to the first occurrence of the recurring event.
daylightOffset = (signed int)[userTimeZone secondsFromGMTForDate: aStartDate]
- (signed int)[userTimeZone secondsFromGMTForDate: aDate];
aDateValue = [NSNumber numberWithInt: [aDateValue intValue] + daylightOffset];
[aRecord setObject: aDateValue forKey: @"c_recurrence_id"];
}
}
}
- (NSArray *) _fetchFields: (NSArray *) fields
@ -341,7 +332,6 @@ static NSArray *tasksFields = nil;
component: component] objectEnumerator];
owner = [currentFolder ownerInContext: context];
ownerUser = [SOGoUser userWithLogin: owner];
/* TODO: this should be handled per-folder rather than per-event. */
isErasable = ([owner isEqualToString: userLogin]
|| [[currentFolder aclsForUser: userLogin] containsObject: SOGoRole_ObjectEraser]);
while ((newInfo = [currentInfos nextObject]))
@ -349,10 +339,12 @@ static NSArray *tasksFields = nil;
if ([fields containsObject: @"editable"])
{
if (folderIsRemote)
// .ics subscriptions are not editable
[newInfo setObject: [NSNumber numberWithInt: 0]
forKey: @"editable"];
else
{
// Identifies whether the active user can edit the event.
role =
[currentFolder roleForComponentsWithAccessClass:
[[newInfo objectForKey: @"c_classification"] intValue]