Merge pull request #221 from zentyal/jvalles/time-shifts-in-events
oc-calendar: Use the time zone provided by the client
This commit is contained in:
commit
20575226b8
|
@ -24,6 +24,7 @@
|
|||
#define MAPISTORECALENDARWRAPPER_H
|
||||
|
||||
#import <NGCards/iCalPerson.h>
|
||||
#import <NGCards/iCalTimeZone.h>
|
||||
#import <Appointments/iCalEntityObject+SOGo.h>
|
||||
|
||||
#import "MAPIStoreObjectProxy.h"
|
||||
|
@ -42,7 +43,7 @@
|
|||
iCalCalendar *calendar;
|
||||
iCalEvent *firstEvent;
|
||||
iCalEvent *event;
|
||||
NSTimeZone *timeZone;
|
||||
iCalTimeZone *timeZone;
|
||||
SOGoUser *user;
|
||||
NSString *senderEmail;
|
||||
NSData *globalObjectId;
|
||||
|
@ -57,12 +58,10 @@
|
|||
+ (id) wrapperWithICalEvent: (iCalEvent *) newEvent
|
||||
andUser: (SOGoUser *) newUser
|
||||
andSenderEmail: (NSString *) newSenderEmail
|
||||
inTimeZone: (NSTimeZone *) newTimeZone
|
||||
withConnectionInfo: (struct mapistore_connection_info *) newConnInfo;
|
||||
- (id) initWithICalEvent: (iCalEvent *) newEvent
|
||||
andUser: (SOGoUser *) newUser
|
||||
andSenderEmail: (NSString *) newSenderEmail
|
||||
inTimeZone: (NSTimeZone *) newTimeZone
|
||||
withConnectionInfo: (struct mapistore_connection_info *) newConnInfo;
|
||||
|
||||
/* getters */
|
||||
|
|
|
@ -37,7 +37,9 @@
|
|||
#import <NGCards/iCalEventChanges.h>
|
||||
#import <NGCards/iCalPerson.h>
|
||||
#import <NGCards/iCalTrigger.h>
|
||||
#import <NGCards/iCalTimeZonePeriod.h>
|
||||
#import <NGCards/NSString+NGCards.h>
|
||||
#import <SOGo/SOGoDomainDefaults.h>
|
||||
#import <SOGo/SOGoUser.h>
|
||||
#import <SOGo/SOGoUserManager.h>
|
||||
|
||||
|
@ -80,7 +82,6 @@ static NSCharacterSet *hexCharacterSet = nil;
|
|||
+ (id) wrapperWithICalEvent: (iCalEvent *) newEvent
|
||||
andUser: (SOGoUser *) newUser
|
||||
andSenderEmail: (NSString *) newSenderEmail
|
||||
inTimeZone: (NSTimeZone *) newTimeZone
|
||||
withConnectionInfo: (struct mapistore_connection_info *) newConnInfo
|
||||
{
|
||||
MAPIStoreAppointmentWrapper *wrapper;
|
||||
|
@ -88,7 +89,6 @@ static NSCharacterSet *hexCharacterSet = nil;
|
|||
wrapper = [[self alloc] initWithICalEvent: newEvent
|
||||
andUser: newUser
|
||||
andSenderEmail: newSenderEmail
|
||||
inTimeZone: newTimeZone
|
||||
withConnectionInfo: newConnInfo];
|
||||
[wrapper autorelease];
|
||||
|
||||
|
@ -182,10 +182,10 @@ static NSCharacterSet *hexCharacterSet = nil;
|
|||
- (id) initWithICalEvent: (iCalEvent *) newEvent
|
||||
andUser: (SOGoUser *) newUser
|
||||
andSenderEmail: (NSString *) newSenderEmail
|
||||
inTimeZone: (NSTimeZone *) newTimeZone
|
||||
withConnectionInfo: (struct mapistore_connection_info *) newConnInfo
|
||||
{
|
||||
NSArray *events;
|
||||
iCalTimeZone *tz;
|
||||
|
||||
if ((self = [self init]))
|
||||
{
|
||||
|
@ -194,9 +194,20 @@ static NSCharacterSet *hexCharacterSet = nil;
|
|||
event = newEvent;
|
||||
events = [calendar events];
|
||||
firstEvent = [events objectAtIndex: 0];
|
||||
ASSIGN (timeZone, newTimeZone);
|
||||
ASSIGN (user, newUser);
|
||||
ASSIGN (senderEmail, newSenderEmail);
|
||||
/* If newEvent comes from the client, we set its time zone in
|
||||
updateFromMAPIProperties. If it is not present, we use the
|
||||
time zone of the user */
|
||||
tz = (iCalTimeZone *) [calendar firstChildWithTag: @"vtimezone"];
|
||||
if (!tz)
|
||||
{
|
||||
tz = [iCalTimeZone timeZoneForName: [[[user userDefaults] timeZone] name]];
|
||||
if (!tz)
|
||||
[self logWithFormat: @"no time zone could be set"];
|
||||
}
|
||||
ASSIGN (timeZone, tz);
|
||||
|
||||
[self _setupITIPContext];
|
||||
}
|
||||
|
||||
|
@ -721,22 +732,15 @@ static NSCharacterSet *hexCharacterSet = nil;
|
|||
inMemCtx: (TALLOC_CTX *) memCtx
|
||||
{
|
||||
NSCalendarDate *dateValue;
|
||||
NSInteger offset;
|
||||
|
||||
// if ([event isRecurrent])
|
||||
// dateValue = [event firstRecurrenceStartDate];
|
||||
// else
|
||||
dateValue = [event startDate];
|
||||
if ([event isAllDay])
|
||||
{
|
||||
offset = -[timeZone secondsFromGMTForDate: dateValue];
|
||||
dateValue = [dateValue dateByAddingYears: 0 months: 0 days: 0
|
||||
hours: 0 minutes: 0
|
||||
seconds: offset];
|
||||
}
|
||||
[dateValue setTimeZone: utcTZ];
|
||||
dateValue = [timeZone shiftedCalendarDateForDate: dateValue];
|
||||
*data = [dateValue asFileTimeInMemCtx: memCtx];
|
||||
|
||||
|
||||
return MAPISTORE_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -749,22 +753,14 @@ static NSCharacterSet *hexCharacterSet = nil;
|
|||
exceptions, where it is the normal start date for the day of the
|
||||
exception. */
|
||||
NSCalendarDate *dateValue;
|
||||
NSInteger offset;
|
||||
|
||||
dateValue = [event recurrenceId];
|
||||
if (!dateValue)
|
||||
dateValue = [event startDate];
|
||||
[dateValue setTimeZone: timeZone];
|
||||
if ([event isAllDay])
|
||||
{
|
||||
offset = -[timeZone secondsFromGMTForDate: dateValue];
|
||||
dateValue = [dateValue dateByAddingYears: 0 months: 0 days: 0
|
||||
hours: 0 minutes: 0
|
||||
seconds: offset];
|
||||
}
|
||||
[dateValue setTimeZone: utcTZ];
|
||||
dateValue = [timeZone shiftedCalendarDateForDate: dateValue];
|
||||
*data = [dateValue asFileTimeInMemCtx: memCtx];
|
||||
|
||||
|
||||
return MAPISTORE_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -772,19 +768,12 @@ static NSCharacterSet *hexCharacterSet = nil;
|
|||
inMemCtx: (TALLOC_CTX *) memCtx
|
||||
{
|
||||
NSCalendarDate *dateValue;
|
||||
NSInteger offset;
|
||||
|
||||
dateValue = [firstEvent startDate];
|
||||
if ([firstEvent isAllDay])
|
||||
{
|
||||
offset = -[timeZone secondsFromGMTForDate: dateValue];
|
||||
dateValue = [dateValue dateByAddingYears: 0 months: 0 days: 0
|
||||
hours: 0 minutes: 0
|
||||
seconds: offset];
|
||||
}
|
||||
[dateValue setTimeZone: utcTZ];
|
||||
dateValue = [timeZone shiftedCalendarDateForDate: dateValue];
|
||||
*data = [dateValue asFileTimeInMemCtx: memCtx];
|
||||
|
||||
|
||||
return MAPISTORE_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -804,8 +793,8 @@ static NSCharacterSet *hexCharacterSet = nil;
|
|||
month: [start monthOfYear]
|
||||
day: [start dayOfMonth]
|
||||
hour: 0 minute: 0 second: 0
|
||||
timeZone: timeZone];
|
||||
[dateValue setTimeZone: utcTZ];
|
||||
timeZone: utcTZ];
|
||||
dateValue = [timeZone shiftedCalendarDateForDate: dateValue];
|
||||
*data = [dateValue asFileTimeInMemCtx: memCtx];
|
||||
rc = MAPISTORE_SUCCESS;
|
||||
}
|
||||
|
@ -829,7 +818,7 @@ static NSCharacterSet *hexCharacterSet = nil;
|
|||
dateValue = [event startDate];
|
||||
offset = [event durationAsTimeInterval];
|
||||
if ([event isAllDay])
|
||||
offset -= [timeZone secondsFromGMTForDate: dateValue];
|
||||
offset -= [[timeZone periodForDate: dateValue] secondsOffsetFromGMT];
|
||||
dateValue = [dateValue dateByAddingYears: 0 months: 0 days: 0
|
||||
hours: 0 minutes: 0
|
||||
seconds: offset];
|
||||
|
@ -847,15 +836,14 @@ static NSCharacterSet *hexCharacterSet = nil;
|
|||
dateValue = [event recurrenceId];
|
||||
if (!dateValue)
|
||||
dateValue = [event startDate];
|
||||
[dateValue setTimeZone: timeZone];
|
||||
offset = [firstEvent durationAsTimeInterval];
|
||||
if ([firstEvent isAllDay])
|
||||
offset -= [timeZone secondsFromGMTForDate: dateValue];
|
||||
offset -= [[timeZone periodForDate: dateValue] secondsOffsetFromGMT];
|
||||
dateValue = [dateValue dateByAddingYears: 0 months: 0 days: 0
|
||||
hours: 0 minutes: 0
|
||||
seconds: offset];
|
||||
*data = [dateValue asFileTimeInMemCtx: memCtx];
|
||||
|
||||
|
||||
return MAPISTORE_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -871,7 +859,7 @@ static NSCharacterSet *hexCharacterSet = nil;
|
|||
dateValue = [firstEvent startDate];
|
||||
offset = [firstEvent durationAsTimeInterval];
|
||||
if ([event isAllDay])
|
||||
offset -= [timeZone secondsFromGMTForDate: dateValue];
|
||||
offset -= [[timeZone periodForDate: dateValue] secondsOffsetFromGMT];
|
||||
dateValue = [dateValue dateByAddingYears: 0 months: 0 days: 0
|
||||
hours: 0 minutes: 0
|
||||
seconds: offset];
|
||||
|
@ -885,23 +873,14 @@ static NSCharacterSet *hexCharacterSet = nil;
|
|||
{
|
||||
enum mapistore_error rc;
|
||||
NSCalendarDate *dateValue;
|
||||
NSInteger offset;
|
||||
iCalRecurrenceRule *rrule;
|
||||
|
||||
if ([event isRecurrent])
|
||||
{
|
||||
rrule = [[event recurrenceRules] objectAtIndex: 0];
|
||||
dateValue = [rrule untilDate];
|
||||
if (dateValue)
|
||||
{
|
||||
if ([event isAllDay])
|
||||
offset = -[timeZone secondsFromGMTForDate: dateValue];
|
||||
else
|
||||
offset = 0;
|
||||
dateValue = [dateValue dateByAddingYears: 0 months: 0 days: 0
|
||||
hours: 0 minutes: 0
|
||||
seconds: offset];
|
||||
}
|
||||
if (dateValue && [event isAllDay])
|
||||
dateValue = [timeZone shiftedCalendarDateForDate: dateValue];
|
||||
else
|
||||
dateValue = [NSCalendarDate dateWithYear: 4500 month: 8 day: 31
|
||||
hour: 23 minute: 59 second: 00
|
||||
|
@ -1338,21 +1317,14 @@ static NSCharacterSet *hexCharacterSet = nil;
|
|||
{
|
||||
enum mapistore_error rc;
|
||||
NSCalendarDate *dateValue;
|
||||
NSInteger offset;
|
||||
|
||||
dateValue = [event recurrenceId];
|
||||
if (dateValue)
|
||||
{
|
||||
rc = MAPISTORE_SUCCESS;
|
||||
|
||||
|
||||
if ([event isAllDay])
|
||||
{
|
||||
offset = -[timeZone secondsFromGMTForDate: dateValue];
|
||||
dateValue = [dateValue dateByAddingYears: 0 months: 0 days: 0
|
||||
hours: 0 minutes: 0
|
||||
seconds: offset];
|
||||
}
|
||||
[dateValue setTimeZone: utcTZ];
|
||||
dateValue = [timeZone shiftedCalendarDateForDate: dateValue];
|
||||
*data = [dateValue asFileTimeInMemCtx: memCtx];
|
||||
}
|
||||
else
|
||||
|
@ -1377,7 +1349,6 @@ static NSCharacterSet *hexCharacterSet = nil;
|
|||
iCalEventChanges *changes;
|
||||
NSArray *changedProperties;
|
||||
NSCalendarDate *dateValue;
|
||||
NSInteger offset;
|
||||
|
||||
changes = [iCalEventChanges changesFromEvent: event toEvent: exceptionEvent];
|
||||
|
||||
|
@ -1385,28 +1356,17 @@ static NSCharacterSet *hexCharacterSet = nil;
|
|||
memset (extendedException, 0, sizeof (struct ExtendedException));
|
||||
extendedException->ChangeHighlight.Size = sizeof (uint32_t);
|
||||
|
||||
dateValue = [exceptionEvent startDate];
|
||||
offset = [timeZone secondsFromGMTForDate: dateValue];
|
||||
dateValue = [dateValue dateByAddingYears: 0 months: 0 days: 0
|
||||
hours: 0 minutes: 0
|
||||
seconds: offset];
|
||||
dateValue = [timeZone computedDateForDate: [exceptionEvent startDate]];
|
||||
exceptionInfo->StartDateTime = [dateValue asMinutesSince1601];
|
||||
extendedException->ChangeHighlight.Value = BIT_CH_START;
|
||||
extendedException->StartDateTime = exceptionInfo->StartDateTime;
|
||||
|
||||
dateValue = [exceptionEvent endDate];
|
||||
offset = [timeZone secondsFromGMTForDate: dateValue];
|
||||
dateValue = [dateValue dateByAddingYears: 0 months: 0 days: 0
|
||||
hours: 0 minutes: 0
|
||||
seconds: offset];
|
||||
dateValue = [timeZone computedDateForDate: [exceptionEvent endDate]];
|
||||
exceptionInfo->EndDateTime = [dateValue asMinutesSince1601];
|
||||
extendedException->ChangeHighlight.Value |= BIT_CH_END;
|
||||
extendedException->EndDateTime = exceptionInfo->EndDateTime;
|
||||
|
||||
dateValue = [[exceptionEvent recurrenceId]
|
||||
dateByAddingYears: 0 months: 0 days: 0
|
||||
hours: 0 minutes: 0
|
||||
seconds: offset];
|
||||
dateValue = [timeZone computedDateForDate: [exceptionEvent recurrenceId]];
|
||||
exceptionInfo->OriginalStartDate = [dateValue asMinutesSince1601];
|
||||
extendedException->OriginalStartDate = exceptionInfo->OriginalStartDate;
|
||||
|
||||
|
@ -1464,7 +1424,6 @@ static NSCharacterSet *hexCharacterSet = nil;
|
|||
arp = talloc_zero (NULL, struct AppointmentRecurrencePattern);
|
||||
[rule fillRecurrencePattern: &arp->RecurrencePattern
|
||||
withEvent: event
|
||||
inTimeZone: timeZone
|
||||
inMemCtx: arp];
|
||||
arp->ReaderVersion2 = 0x00003006;
|
||||
arp->WriterVersion2 = 0x00003008; /* 0x3008 for compatibility with
|
||||
|
@ -1475,7 +1434,7 @@ static NSCharacterSet *hexCharacterSet = nil;
|
|||
fields are relative to midnight of those days ([MS-OXOCAL] 2.2.1.44.5),
|
||||
so no time zone adjustment is needed */
|
||||
if (![event isAllDay])
|
||||
[firstStartDate setTimeZone: timeZone];
|
||||
firstStartDate = [timeZone computedDateForDate: firstStartDate];
|
||||
startMinutes = ([firstStartDate hourOfDay] * 60
|
||||
+ [firstStartDate minuteOfHour]);
|
||||
arp->StartTimeOffset = startMinutes;
|
||||
|
@ -1701,15 +1660,16 @@ ReservedBlockEE2Size: 00 00 00 00
|
|||
fromDate: (NSCalendarDate *) instanceDate;
|
||||
{
|
||||
uint16_t year;
|
||||
NSCalendarDate *dateValue;
|
||||
|
||||
if (instanceDate)
|
||||
{
|
||||
[instanceDate setTimeZone: timeZone];
|
||||
year = [instanceDate yearOfCommonEra];
|
||||
dateValue = [timeZone computedDateForDate: instanceDate];
|
||||
year = [dateValue yearOfCommonEra];
|
||||
newGlobalId->YH = year >> 8;
|
||||
newGlobalId->YL = year & 0xff;
|
||||
newGlobalId->Month = [instanceDate monthOfYear];
|
||||
newGlobalId->D = [instanceDate dayOfMonth];
|
||||
newGlobalId->Month = [dateValue monthOfYear];
|
||||
newGlobalId->D = [dateValue dayOfMonth];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1974,7 +1934,6 @@ ReservedBlockEE2Size: 00 00 00 00
|
|||
if (alarm)
|
||||
{
|
||||
alarmDate = [alarm nextAlarmDate];
|
||||
[alarmDate setTimeZone: utcTZ];
|
||||
*data = [alarmDate asFileTimeInMemCtx: memCtx];
|
||||
}
|
||||
else
|
||||
|
@ -2036,8 +1995,7 @@ ReservedBlockEE2Size: 00 00 00 00
|
|||
enum mapistore_error rc;
|
||||
NSString *tzid;
|
||||
|
||||
tzid = [(iCalDateTime *) [event firstChildWithTag: @"dtstart"]
|
||||
value: 0 ofAttribute: @"tzid"];
|
||||
tzid = [timeZone tzId];
|
||||
if ([tzid length] > 0)
|
||||
{
|
||||
*data = [tzid asUnicodeInMemCtx: memCtx];
|
||||
|
@ -2053,16 +2011,9 @@ ReservedBlockEE2Size: 00 00 00 00
|
|||
inMemCtx: (TALLOC_CTX *) memCtx
|
||||
{
|
||||
enum mapistore_error rc;
|
||||
iCalTimeZone *icalTZ;
|
||||
|
||||
icalTZ = [(iCalDateTime *) [event firstChildWithTag: @"dtstart"] timeZone];
|
||||
if (icalTZ)
|
||||
{
|
||||
*data = [icalTZ asTimeZoneStructInMemCtx: memCtx];
|
||||
rc = MAPISTORE_SUCCESS;
|
||||
}
|
||||
else
|
||||
rc = MAPISTORE_ERR_NOT_FOUND;
|
||||
*data = [timeZone asTimeZoneStructInMemCtx: memCtx];
|
||||
rc = MAPISTORE_SUCCESS;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
@ -2071,24 +2022,16 @@ ReservedBlockEE2Size: 00 00 00 00
|
|||
inMemCtx: (TALLOC_CTX *) memCtx
|
||||
{
|
||||
enum mapistore_error rc;
|
||||
iCalTimeZone *icalTZ;
|
||||
|
||||
/* [MS-OXOCAL] 3.1.5.5.1: This property is used in floating (all-day) events,
|
||||
specified in floating time, to convert the start date from UTC to the user's
|
||||
time zone */
|
||||
if ([event isAllDay])
|
||||
icalTZ = [iCalTimeZone timeZoneForName: [timeZone timeZoneName]];
|
||||
else if ([event isRecurrent])
|
||||
icalTZ = [(iCalDateTime *) [event firstChildWithTag: @"dtstart"] timeZone];
|
||||
else
|
||||
icalTZ = nil;
|
||||
|
||||
if (icalTZ)
|
||||
if ([event isAllDay] | [event isRecurrent])
|
||||
{
|
||||
/* [MS-OXOCAL] 2.2.1.42: This property can only have the E flag set in the
|
||||
TimeZoneDefinition struct */
|
||||
*data = [icalTZ asZoneTimeDefinitionWithFlags: TZRULE_FLAG_EFFECTIVE_TZREG
|
||||
inMemCtx: memCtx];
|
||||
*data = [timeZone asZoneTimeDefinitionWithFlags: TZRULE_FLAG_EFFECTIVE_TZREG
|
||||
inMemCtx: memCtx];
|
||||
rc = MAPISTORE_SUCCESS;
|
||||
}
|
||||
else
|
||||
|
|
|
@ -58,7 +58,6 @@
|
|||
wrapperWithICalEvent: [newContainer event]
|
||||
andUser: [userContext sogoUser]
|
||||
andSenderEmail: nil
|
||||
inTimeZone: [userContext timeZone]
|
||||
withConnectionInfo: [context connectionInfo]];
|
||||
[self addProxy: appointmentWrapper];
|
||||
}
|
||||
|
|
|
@ -197,7 +197,6 @@ static Class NSArrayK, MAPIStoreAppointmentWrapperK;
|
|||
= [MAPIStoreAppointmentWrapper wrapperWithICalEvent: masterEvent
|
||||
andUser: [userContext sogoUser]
|
||||
andSenderEmail: nil
|
||||
inTimeZone: [userContext timeZone]
|
||||
withConnectionInfo: [context connectionInfo]];
|
||||
[self addProxy: appointmentWrapper];
|
||||
}
|
||||
|
|
|
@ -340,7 +340,6 @@ _compareBodyKeysByPriority (id entry1, id entry2, void *data)
|
|||
wrapperWithICalEvent: event
|
||||
andUser: [context activeUser]
|
||||
andSenderEmail: senderEmail
|
||||
inTimeZone: [[self userContext] timeZone]
|
||||
withConnectionInfo: [context connectionInfo]];
|
||||
[appointmentWrapper retain];
|
||||
}
|
||||
|
|
|
@ -25,12 +25,9 @@
|
|||
|
||||
#include <talloc.h>
|
||||
|
||||
#import <Foundation/NSTimeZone.h>
|
||||
|
||||
#import <NGCards/iCalCalendar.h>
|
||||
#import <NGCards/iCalRecurrenceRule.h>
|
||||
|
||||
@class NSTimeZone;
|
||||
#import <NGCards/iCalTimeZone.h>
|
||||
|
||||
@class iCalEvent;
|
||||
@class iCalRepeatableEntityObject;
|
||||
|
@ -46,7 +43,7 @@
|
|||
fromRecurrencePattern: (struct RecurrencePattern *) rp
|
||||
withExceptions: (struct ExceptionInfo *) exInfos
|
||||
andExceptionCount: (uint16_t) exInfoCount
|
||||
inTimeZone: (NSTimeZone *) tz;
|
||||
inTimeZone: (iCalTimeZone *) tz;
|
||||
|
||||
@end
|
||||
|
||||
|
@ -54,7 +51,6 @@
|
|||
|
||||
- (void) fillRecurrencePattern: (struct RecurrencePattern *) rp
|
||||
withEvent: (iCalEvent *) event
|
||||
inTimeZone: (NSTimeZone *) timeZone
|
||||
inMemCtx: (TALLOC_CTX *) memCtx;
|
||||
|
||||
@end
|
||||
|
|
|
@ -24,7 +24,6 @@
|
|||
#import <Foundation/NSCalendarDate.h>
|
||||
#import <Foundation/NSSet.h>
|
||||
#import <Foundation/NSString.h>
|
||||
#import <Foundation/NSTimeZone.h>
|
||||
|
||||
#import <NGExtensions/NSCalendarDate+misc.h>
|
||||
#import <NGExtensions/NSObject+Logs.h>
|
||||
|
@ -35,6 +34,7 @@
|
|||
#import <NGCards/iCalRepeatableEntityObject.h>
|
||||
#import <NGCards/iCalRecurrenceRule.h>
|
||||
#import <NGCards/iCalTimeZone.h>
|
||||
#import <NGCards/iCalTimeZonePeriod.h>
|
||||
|
||||
#import "NSDate+MAPIStore.h"
|
||||
#import "MAPIStoreRecurrenceUtils.h"
|
||||
|
@ -51,7 +51,7 @@
|
|||
fromRecurrencePattern: (struct RecurrencePattern *) rp
|
||||
withExceptions: (struct ExceptionInfo *) exInfos
|
||||
andExceptionCount: (uint16_t) exInfoCount
|
||||
inTimeZone: (NSTimeZone *) tz
|
||||
inTimeZone: (iCalTimeZone *) tz
|
||||
|
||||
{
|
||||
NSCalendarDate *startDate, *olEndDate, *untilDate, *exDate;
|
||||
|
@ -63,7 +63,7 @@
|
|||
iCalWeekOccurrence weekOccurrence;
|
||||
iCalWeekOccurrences dayMaskDays;
|
||||
NSUInteger count, max;
|
||||
NSInteger bySetPos;
|
||||
NSInteger bySetPos, tzOffset;
|
||||
unsigned char maskValue;
|
||||
|
||||
[entity removeAllRecurrenceRules];
|
||||
|
@ -242,9 +242,10 @@
|
|||
{
|
||||
/* The OriginalStartDate is in local time */
|
||||
exDate = [NSDate dateFromMinutesSince1601: exInfos[count].OriginalStartDate];
|
||||
tzOffset = -[[tz periodForDate: exDate] secondsOffsetFromGMT];
|
||||
exDate = [exDate dateByAddingYears: 0 months: 0 days: 0
|
||||
hours: 0 minutes: 0
|
||||
seconds: - [tz secondsFromGMT]];
|
||||
seconds: tzOffset];
|
||||
[exceptionDates removeObject: exDate];
|
||||
}
|
||||
}
|
||||
|
@ -263,7 +264,6 @@
|
|||
|
||||
- (void) fillRecurrencePattern: (struct RecurrencePattern *) rp
|
||||
withEvent: (iCalEvent *) event
|
||||
inTimeZone: (NSTimeZone *) timeZone
|
||||
inMemCtx: (TALLOC_CTX *) memCtx
|
||||
{
|
||||
iCalRecurrenceFrequency freq;
|
||||
|
@ -279,10 +279,8 @@
|
|||
NSMutableArray *deletedDates, *modifiedDates;
|
||||
|
||||
startDate = [event firstRecurrenceStartDate];
|
||||
[startDate setTimeZone: timeZone];
|
||||
endDate = [event lastPossibleRecurrenceStartDate];
|
||||
[endDate setTimeZone: timeZone];
|
||||
|
||||
|
||||
rp->ReaderVersion = 0x3004;
|
||||
rp->WriterVersion = 0x3004;
|
||||
|
||||
|
|
|
@ -37,6 +37,8 @@
|
|||
|
||||
- (BOOL) isNever; /* occurs on 4500-12-31 */
|
||||
|
||||
+ (NSCalendarDate *) dateFromSystemTime: (struct SYSTEMTIME) date
|
||||
andRuleYear: (uint16_t) rYear;
|
||||
@end
|
||||
|
||||
NSComparisonResult NSDateCompare (id date1, id date2, void *);
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#import <Foundation/NSString.h>
|
||||
#import <Foundation/NSTimeZone.h>
|
||||
|
||||
#import "MAPIStoreTypes.h"
|
||||
#import "NSDate+MAPIStore.h"
|
||||
|
||||
#undef DEBUG
|
||||
|
@ -48,7 +49,7 @@ _setupRefDate ()
|
|||
refDate = [[NSCalendarDate alloc]
|
||||
initWithYear: 1601 month: 1 day: 1
|
||||
hour: 0 minute: 0 second: 0
|
||||
timeZone: [NSTimeZone timeZoneWithName: @"UTC"]];
|
||||
timeZone: utcTZ];
|
||||
}
|
||||
|
||||
+ (NSCalendarDate *) dateFromMinutesSince1601: (uint32_t) minutes
|
||||
|
@ -128,6 +129,64 @@ _setupRefDate ()
|
|||
return [calDate yearOfCommonEra] == 4500;
|
||||
}
|
||||
|
||||
+ (NSCalendarDate *) dateFromSystemTime: (struct SYSTEMTIME) date
|
||||
andRuleYear: (uint16_t) rYear
|
||||
{
|
||||
NSCalendarDate *result;
|
||||
NSInteger daysToDate;
|
||||
NSUInteger firstDayOfWeek, year;
|
||||
|
||||
/* ([MS-OXOCAL] 2.2.1.41.1) When we're provided an absolute date (i.e., it
|
||||
happens once), the SYSTEMTIME structure is enough to fill the date.
|
||||
When we're parsing a SYSTEMTIME field from a time zone rule, however, a
|
||||
relative date can be provided for the peroidicity of its periods. In this
|
||||
scenario, the wYear field is empty and we have to use the wYear field in
|
||||
the parent rule */
|
||||
if (date.wYear != 0)
|
||||
year = date.wYear;
|
||||
else
|
||||
year = rYear;
|
||||
|
||||
/* The wDay field indicates the occurrence of the wDayOfWeek within the month.
|
||||
The 5th occurrence means the last one, even if it is the 4th. */
|
||||
if (date.wDay < 5)
|
||||
{
|
||||
result = [[NSCalendarDate alloc] initWithYear: year month: date.wMonth day: 1
|
||||
hour: date.wHour minute: date.wMinute second: date.wSecond
|
||||
timeZone: utcTZ];
|
||||
[result autorelease];
|
||||
|
||||
firstDayOfWeek = [result dayOfWeek];
|
||||
|
||||
daysToDate = 7 * (date.wDay - 1) + date.wDayOfWeek - firstDayOfWeek;
|
||||
if (date.wDayOfWeek < firstDayOfWeek)
|
||||
daysToDate += 7;
|
||||
|
||||
result = [result dateByAddingYears: 0 months: 0 days: daysToDate
|
||||
hours: 0 minutes: 0
|
||||
seconds: 0];
|
||||
}
|
||||
else
|
||||
{
|
||||
result = [[NSCalendarDate alloc] initWithYear: year month: date.wMonth + 1 day: 1
|
||||
hour: date.wHour minute: date.wMinute second: date.wSecond
|
||||
timeZone: utcTZ];
|
||||
[result autorelease];
|
||||
|
||||
firstDayOfWeek = [result dayOfWeek];
|
||||
|
||||
daysToDate = date.wDayOfWeek - firstDayOfWeek;
|
||||
if (date.wDayOfWeek >= firstDayOfWeek)
|
||||
daysToDate -= 7;
|
||||
|
||||
result = [result dateByAddingYears: 0 months: 0 days: daysToDate
|
||||
hours: 0 minutes: 0
|
||||
seconds: 0];
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
NSComparisonResult
|
||||
|
|
|
@ -36,6 +36,7 @@
|
|||
#import <NGCards/iCalDateTime.h>
|
||||
#import <NGCards/iCalPerson.h>
|
||||
#import <NGCards/iCalTimeZone.h>
|
||||
#import <NGCards/iCalTimeZonePeriod.h>
|
||||
#import <NGCards/iCalTrigger.h>
|
||||
#import <SOGo/SOGoPermissions.h>
|
||||
#import <SOGo/SOGoUser.h>
|
||||
|
@ -70,11 +71,12 @@
|
|||
#include <mapistore/mapistore_nameid.h>
|
||||
|
||||
#import "iCalEvent+MAPIStore.h"
|
||||
#import "iCalTimeZone+MAPIStore.h"
|
||||
|
||||
@implementation iCalEvent (MAPIStoreProperties)
|
||||
|
||||
- (void) _setupEventRecurrence: (NSData *) mapiRecurrenceData
|
||||
inTimeZone: (NSTimeZone *) tz
|
||||
inTimeZone: (iCalTimeZone *) tz
|
||||
inMemCtx: (TALLOC_CTX *) memCtx
|
||||
{
|
||||
struct Binary_r *blob;
|
||||
|
@ -250,10 +252,8 @@
|
|||
BOOL isAllDay;
|
||||
iCalDateTime *start, *end;
|
||||
iCalTimeZone *tz;
|
||||
NSTimeZone *userTimeZone;
|
||||
NSString *priority, *class = nil;
|
||||
NSString *priority, *class = nil, *tzDescription = nil;
|
||||
NSUInteger responseStatus = 0;
|
||||
NSInteger tzOffset;
|
||||
SOGoUser *ownerUser;
|
||||
id value;
|
||||
|
||||
|
@ -274,7 +274,31 @@
|
|||
[self setAccessClass: @"PUBLIC"];
|
||||
}
|
||||
|
||||
userTimeZone = [userContext timeZone];
|
||||
/* Time zone = PidLidAppointmentTimeZoneDefinitionRecur
|
||||
or PidLidAppointmentTimeZoneDefinition[Start|End]Display */
|
||||
value = [properties objectForKey: MAPIPropertyKey (PidLidAppointmentTimeZoneDefinitionStartDisplay)];
|
||||
if (!value)
|
||||
{
|
||||
value = [properties objectForKey: MAPIPropertyKey (PidLidAppointmentTimeZoneDefinitionEndDisplay)];
|
||||
if (!value)
|
||||
{
|
||||
/* If PidLidtimeZoneStruct, TZID SHOULD come from PidLidTimeZoneDescription,
|
||||
if PidLidAppointmentTimeZoneDefinition[Start|End]Display it MUST be derived from KeyName
|
||||
(MS-OXCICAL] 2.1.3.1.1.19.1) */
|
||||
value = [properties objectForKey: MAPIPropertyKey (PidLidAppointmentTimeZoneDefinitionRecur)];
|
||||
tzDescription = [properties objectForKey: MAPIPropertyKey (PidLidTimeZoneDescription)];
|
||||
}
|
||||
}
|
||||
if (value)
|
||||
{
|
||||
tz = [[iCalTimeZone alloc] iCalTimeZoneFromDefinition: value
|
||||
withDescription: tzDescription
|
||||
inMemCtx: memCtx];
|
||||
}
|
||||
else
|
||||
/* The client is more likely to have the webmail's time zone than any other */
|
||||
tz = [iCalTimeZone timeZoneForName: [[userContext timeZone] name]];
|
||||
[(iCalCalendar *) parent addTimeZone: tz];
|
||||
|
||||
/* CREATED */
|
||||
value = [properties objectForKey: MAPIPropertyKey (PidTagCreationTime)];
|
||||
|
@ -306,20 +330,13 @@
|
|||
objectForKey: MAPIPropertyKey (PidLidAppointmentSubType)];
|
||||
if (value)
|
||||
isAllDay = [value boolValue];
|
||||
if (!isAllDay)
|
||||
{
|
||||
tz = [iCalTimeZone timeZoneForName: [userTimeZone name]];
|
||||
[(iCalCalendar *) parent addTimeZone: tz];
|
||||
}
|
||||
else
|
||||
tz = nil;
|
||||
|
||||
// recurrence-id
|
||||
value
|
||||
= [properties objectForKey: MAPIPropertyKey (PidLidExceptionReplaceTime)];
|
||||
if (value)
|
||||
[self setRecurrenceId: value];
|
||||
|
||||
|
||||
// start
|
||||
value = [properties objectForKey: MAPIPropertyKey (PidLidAppointmentStartWhole)];
|
||||
if (!value)
|
||||
|
@ -330,15 +347,7 @@
|
|||
[start setTimeZone: tz];
|
||||
if (isAllDay)
|
||||
{
|
||||
/* when user TZ is positive (East) all-day events were not
|
||||
shown properly in SOGo UI. This day delay fixes it */
|
||||
tzOffset = [userTimeZone secondsFromGMTForDate: value];
|
||||
if (tzOffset > 0)
|
||||
{
|
||||
value = [value dateByAddingYears: 0 months: 0 days: 1
|
||||
hours: 0 minutes: 0
|
||||
seconds: 0];
|
||||
}
|
||||
/* All-day events are set in floating time ([MS-OXCICAL] 2.1.3.1.1.20.8) */
|
||||
[start setDate: value];
|
||||
[start setTimeZone: nil];
|
||||
}
|
||||
|
@ -356,15 +365,7 @@
|
|||
[end setTimeZone: tz];
|
||||
if (isAllDay)
|
||||
{
|
||||
/* when user TZ is positive (East) all-day events were not
|
||||
shown properly in SOGo UI. This day delay fixes it */
|
||||
tzOffset = [userTimeZone secondsFromGMTForDate: value];
|
||||
if (tzOffset > 0)
|
||||
{
|
||||
value = [value dateByAddingYears: 0 months: 0 days: 1
|
||||
hours: 0 minutes: 0
|
||||
seconds: 0];
|
||||
}
|
||||
/* All-day events are set in floating time ([MS-OXCICAL] 2.1.3.1.1.20.8) */
|
||||
[end setDate: value];
|
||||
[end setTimeZone: nil];
|
||||
}
|
||||
|
@ -467,7 +468,7 @@
|
|||
value = [properties
|
||||
objectForKey: MAPIPropertyKey (PidLidAppointmentRecur)];
|
||||
if (value)
|
||||
[self _setupEventRecurrence: value inTimeZone: userTimeZone inMemCtx: memCtx];
|
||||
[self _setupEventRecurrence: value inTimeZone: tz inMemCtx: memCtx];
|
||||
|
||||
/* alarm */
|
||||
[self _setupEventAlarmFromProperties: properties];
|
||||
|
|
|
@ -30,6 +30,11 @@
|
|||
- (struct Binary_r *) asTimeZoneStructInMemCtx: (TALLOC_CTX *) memCtx;
|
||||
- (struct Binary_r *) asZoneTimeDefinitionWithFlags: (enum TZRuleFlag) flags
|
||||
inMemCtx: (TALLOC_CTX *) memCtx;
|
||||
- (iCalTimeZone *) iCalTimeZoneFromDefinition: (NSData *) value
|
||||
withDescription: (NSString *) description
|
||||
inMemCtx: (TALLOC_CTX *) memCtx;
|
||||
- (NSCalendarDate *) shiftedCalendarDateForDate: (NSCalendarDate *) date;
|
||||
|
||||
|
||||
@end
|
||||
|
||||
|
|
|
@ -23,11 +23,15 @@
|
|||
#import <Foundation/NSArray.h>
|
||||
#import <Foundation/NSCalendarDate.h>
|
||||
#import <Foundation/NSString.h>
|
||||
#import <Foundation/NSTimeZone.h>
|
||||
#import <NGCards/iCalByDayMask.h>
|
||||
#import <NGCards/iCalDateTime.h>
|
||||
#import <NGCards/iCalTimeZonePeriod.h>
|
||||
#import <NGCards/iCalRecurrenceRule.h>
|
||||
|
||||
#import "NSString+MAPIStore.h"
|
||||
#import "NSData+MAPIStore.h"
|
||||
#import "NSDate+MAPIStore.h"
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
@ -36,6 +40,7 @@
|
|||
#include <libmapi/libmapi.h>
|
||||
|
||||
#import "iCalTimeZone+MAPIStore.h"
|
||||
#import "MAPIStoreTypes.h"
|
||||
|
||||
@interface iCalTimeZonePeriod (MAPIStorePropertiesPrivate)
|
||||
|
||||
|
@ -103,18 +108,18 @@
|
|||
{
|
||||
iCalTimeZonePeriod *period;
|
||||
struct TimeZoneStruct tz;
|
||||
int lBias, dlBias;
|
||||
int32_t lBias, dlBias;
|
||||
|
||||
memset (&tz, 0, sizeof (struct TimeZoneStruct));
|
||||
period = [self _mostRecentPeriodWithName: @"STANDARD"];
|
||||
lBias = -[period secondsOffsetFromGMT] / 60;
|
||||
tz.lBias = (uint32_t) lBias;
|
||||
tz.lBias = lBias;
|
||||
[period _fillTZDate: &tz.stStandardDate];
|
||||
period = [self _mostRecentPeriodWithName: @"DAYLIGHT"];
|
||||
if (!period)
|
||||
tz.stStandardDate.wMonth = 0;
|
||||
dlBias = -([period secondsOffsetFromGMT] / 60) - lBias;
|
||||
tz.lDaylightBias = (uint32_t) (dlBias);
|
||||
tz.lDaylightBias = dlBias;
|
||||
[period _fillTZDate: &tz.stDaylightDate];
|
||||
tz.wStandardYear = tz.stStandardDate.wYear;
|
||||
tz.wDaylightYear = tz.stDaylightDate.wYear;
|
||||
|
@ -153,18 +158,220 @@
|
|||
period = [self _mostRecentPeriodWithName: @"STANDARD"];
|
||||
rule.wYear = [[period startDate] yearOfCommonEra];
|
||||
lBias = -[period secondsOffsetFromGMT] / 60;
|
||||
rule.lBias = (uint32_t) lBias;
|
||||
rule.lBias = lBias;
|
||||
[period _fillTZDate: &rule.stStandardDate];
|
||||
period = [self _mostRecentPeriodWithName: @"DAYLIGHT"];
|
||||
if (!period)
|
||||
rule.stStandardDate.wMonth = 0;
|
||||
dlBias = -([period secondsOffsetFromGMT] / 60) - lBias;
|
||||
rule.lDaylightBias = (uint32_t) (dlBias);
|
||||
rule.lDaylightBias = dlBias;
|
||||
[period _fillTZDate: &rule.stDaylightDate];
|
||||
|
||||
|
||||
return set_TimeZoneDefinition (memCtx, &definition);
|
||||
}
|
||||
|
||||
- (NSString *) _offsetStringFromOffset: (NSInteger) offset
|
||||
{
|
||||
NSInteger offsetHours, offsetMins;
|
||||
NSString *offsetSign;
|
||||
|
||||
/* The offset format is, eg, "+0200" for 2 hours 0 minutes ahead */
|
||||
if (offset < 0)
|
||||
offsetSign = @"-";
|
||||
else
|
||||
offsetSign = @"+";
|
||||
offsetHours = abs (offset) / 60;
|
||||
offsetMins = abs (offset) % 60;
|
||||
|
||||
return [NSString stringWithFormat: @"%@%d%d%d%d",
|
||||
offsetSign, offsetHours / 10, offsetHours % 10,
|
||||
offsetMins / 10, offsetMins % 10];
|
||||
|
||||
}
|
||||
|
||||
- (NSString *) _rRuleStringFromSystemTime: (struct SYSTEMTIME) date
|
||||
{
|
||||
NSString *result, *byDay;
|
||||
|
||||
/* The conversion tables between the SYSTEMTIME fields and the RRULE ones
|
||||
can be found at [MS-OXCICAL] 2.1.3.2.1 */
|
||||
if (date.wDay == 5)
|
||||
byDay = @"-1";
|
||||
else
|
||||
byDay = [NSString stringWithFormat: @"%d", date.wDay];
|
||||
|
||||
switch (date.wDayOfWeek)
|
||||
{
|
||||
case iCalWeekDaySunday:
|
||||
byDay = [byDay stringByAppendingString: @"SU"];
|
||||
break;
|
||||
case iCalWeekDayMonday:
|
||||
byDay = [byDay stringByAppendingString: @"MO"];
|
||||
break;
|
||||
case iCalWeekDayTuesday:
|
||||
byDay = [byDay stringByAppendingString: @"TU"];
|
||||
break;
|
||||
case iCalWeekDayWednesday:
|
||||
byDay = [byDay stringByAppendingString: @"WE"];
|
||||
break;
|
||||
case iCalWeekDayThursday:
|
||||
byDay = [byDay stringByAppendingString: @"TH"];
|
||||
break;
|
||||
case iCalWeekDayFriday:
|
||||
byDay = [byDay stringByAppendingString: @"FR"];
|
||||
break;
|
||||
case iCalWeekDaySaturday:
|
||||
byDay = [byDay stringByAppendingString: @"SA"];
|
||||
break;
|
||||
}
|
||||
|
||||
result = [NSString stringWithFormat: @"FREQ=YEARLY;BYDAY=%@;BYMONTH=%d", byDay, date.wMonth];
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
- (iCalTimeZone *) iCalTimeZoneFromDefinition: (NSData *) value
|
||||
withDescription: (NSString *) description
|
||||
inMemCtx: (TALLOC_CTX *) memCtx
|
||||
{
|
||||
BOOL daylightDefined = NO, ruleFound = NO;
|
||||
iCalDateTime *daylightStart, *standardStart;
|
||||
iCalRecurrenceRule *daylightRRule, *standardRRule;
|
||||
iCalTimeZone *tz = nil;
|
||||
iCalTimeZonePeriod *daylight, *standard;
|
||||
NSCalendarDate *dlStartValue, *stStartValue;
|
||||
NSString *strOffsetFrom, *strOffsetTo, *tzID;
|
||||
char *keyName;
|
||||
struct Binary_r *binValue;
|
||||
struct SYSTEMTIME initDate;
|
||||
struct TimeZoneDefinition *definition;
|
||||
struct TZRule rule;
|
||||
uint16_t count;
|
||||
|
||||
binValue = [value asBinaryInMemCtx: memCtx];
|
||||
definition = get_TimeZoneDefinition (memCtx, binValue);
|
||||
|
||||
if (!definition)
|
||||
return nil;
|
||||
|
||||
if (!definition->cRules)
|
||||
goto end;
|
||||
|
||||
for (count = 0; count < definition->cRules; count++)
|
||||
{
|
||||
/* ([MS-OXCICAL] 2.1.3.1.1.19) The TZRule with the
|
||||
TZRULE_FLAG_EFFECTIVE_TZREG bit set in the TZRule flags field
|
||||
is the one that MUST be exported */
|
||||
if (definition->TZRules[count].flags & TZRULE_FLAG_EFFECTIVE_TZREG)
|
||||
{
|
||||
rule = definition->TZRules[count];
|
||||
ruleFound = YES;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!ruleFound)
|
||||
goto end;
|
||||
|
||||
if (!description)
|
||||
{
|
||||
/* The cbHeader field contains the size, in bytes of the Reserved (2b),
|
||||
cchKeyName (2b) keyName (variable Unicode string) and cRules (2b)
|
||||
([MS-OXOCAL] 2.2.1.41). The keyName field is a non-NULL-terminated
|
||||
char array. */
|
||||
keyName = talloc_strndup (memCtx, definition->keyName, (definition->cbHeader - 6) / 2);
|
||||
tzID = [NSString stringWithCString: keyName
|
||||
encoding: [NSString defaultCStringEncoding]];
|
||||
talloc_free (keyName);
|
||||
}
|
||||
else
|
||||
tzID = [NSString stringWithString: description];
|
||||
|
||||
tz = [iCalTimeZone groupWithTag: @"vtimezone"];
|
||||
[tz addChild: [CardElement simpleElementWithTag: @"tzid"
|
||||
value: tzID]];
|
||||
|
||||
if (rule.stStandardDate.wMonth != 0)
|
||||
daylightDefined = YES;
|
||||
|
||||
/* STANDARD TIME ([MS-OXCICAL] 2.1.3.1.1.19.2) */
|
||||
standard = [iCalTimeZonePeriod groupWithTag: @"standard"];
|
||||
|
||||
/* TZOFFSETFROM = -1 * (PidLidTimeZoneStruct.lBias + PidLidTimeZoneStruct.lDaylightBias) */
|
||||
strOffsetFrom = [self _offsetStringFromOffset: -1 * (rule.lBias + rule.lDaylightBias)];
|
||||
[standard addChild: [CardElement simpleElementWithTag: @"tzoffsetfrom"
|
||||
value: strOffsetFrom]];
|
||||
|
||||
/* TZOFFSETTO = -1 * (PidLidTimeZoneStruct.lBias + PidLidTimeZoneStruct.lStandardBias) */
|
||||
strOffsetTo = [self _offsetStringFromOffset: -1 * (rule.lBias + rule.lStandardBias)];
|
||||
[standard addChild: [CardElement simpleElementWithTag: @"tzoffsetto"
|
||||
value: strOffsetTo]];
|
||||
|
||||
/* DTSTART & RRULE are derived from the stStandardDate and wYear properties */
|
||||
standardStart = [iCalDateTime elementWithTag: @"dtstart"];
|
||||
|
||||
initDate = rule.stStandardDate;
|
||||
stStartValue = [NSCalendarDate dateFromSystemTime: initDate
|
||||
andRuleYear: rule.wYear];
|
||||
|
||||
[standardStart setDateTime: stStartValue];
|
||||
[standard addChild: standardStart];
|
||||
|
||||
if (daylightDefined)
|
||||
{
|
||||
standardRRule = [[iCalRecurrenceRule alloc] initWithString: [self _rRuleStringFromSystemTime: initDate]];
|
||||
[standard addChild: standardRRule];
|
||||
|
||||
/* DAYLIGHT SAVING TIME ([MS-OXCICAL] 2.1.3.1.1.19.3) */
|
||||
daylight = [iCalTimeZonePeriod groupWithTag: @"daylight"];
|
||||
/* TZOFFSETFROM = -1 * (PidLidTimeZoneStruct.lBias + PidLidTimeZoneStruct.lStandardBias) */
|
||||
[daylight addChild: [CardElement simpleElementWithTag: @"tzoffsetfrom"
|
||||
value: strOffsetTo]];
|
||||
/* TZOFFSETTO = -1 * (PidLidTimeZoneStruct.lBias + PidLidTimeZoneStruct.lDaylightBias) */
|
||||
[daylight addChild: [CardElement simpleElementWithTag: @"tzoffsetto"
|
||||
value: strOffsetFrom]];
|
||||
|
||||
/* DTSTART & RRULE are derived from the stDaylightDate and wYear properties */
|
||||
daylightStart = [iCalDateTime elementWithTag: @"dtstart"];
|
||||
initDate = rule.stDaylightDate;
|
||||
dlStartValue = [NSCalendarDate dateFromSystemTime: initDate
|
||||
andRuleYear: rule.wYear];
|
||||
|
||||
[daylightStart setDateTime: dlStartValue];
|
||||
[daylight addChild: daylightStart];
|
||||
|
||||
daylightRRule = [[iCalRecurrenceRule alloc] initWithString: [self _rRuleStringFromSystemTime: initDate]];
|
||||
[daylight addChild: daylightRRule];
|
||||
[tz addChild: daylight];
|
||||
}
|
||||
[tz addChild: standard];
|
||||
|
||||
end:
|
||||
|
||||
talloc_free (definition);
|
||||
return tz;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adjust a date in this vTimeZone to its representation in UTC
|
||||
* Example: Timezone is +0001, the date is 2015-12-15 00:00:00 +0000
|
||||
* it returns 2015-12-14 23:00:00 +0000
|
||||
* @param date the date to adjust to the timezone.
|
||||
* @return a new GMT date adjusted with the offset of the timezone.
|
||||
*/
|
||||
- (NSCalendarDate *) shiftedCalendarDateForDate: (NSCalendarDate *) date
|
||||
{
|
||||
NSCalendarDate *tmpDate;
|
||||
|
||||
tmpDate = [date copy];
|
||||
[tmpDate autorelease];
|
||||
|
||||
[tmpDate setTimeZone: utcTZ];
|
||||
|
||||
return [tmpDate addYear: 0 month: 0 day: 0
|
||||
hour: 0 minute: 0
|
||||
second: -[[self periodForDate: tmpDate] secondsOffsetFromGMT]];
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
Loading…
Reference in a new issue