From d2ea6fef2eaca8b82b3389b5d993171b094ac0d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juan=20Vall=C3=A9s?= Date: Fri, 11 Dec 2015 10:36:59 +0100 Subject: [PATCH] oc-calendar: Initialise NSCalendarDate with a SYSTEMTIME struct The method computes the date of a SYSTEMTIME structure, in which the day within the month is given by the Nth occurrence of a weekday (see [MS-OXOCAL] 2.2.1.39). --- OpenChange/NSDate+MAPIStore.h | 2 ++ OpenChange/NSDate+MAPIStore.m | 61 ++++++++++++++++++++++++++++++++++- 2 files changed, 62 insertions(+), 1 deletion(-) diff --git a/OpenChange/NSDate+MAPIStore.h b/OpenChange/NSDate+MAPIStore.h index 0e417d21f..d61df7b11 100644 --- a/OpenChange/NSDate+MAPIStore.h +++ b/OpenChange/NSDate+MAPIStore.h @@ -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 *); diff --git a/OpenChange/NSDate+MAPIStore.m b/OpenChange/NSDate+MAPIStore.m index b96812adf..b8f09dcc6 100644 --- a/OpenChange/NSDate+MAPIStore.m +++ b/OpenChange/NSDate+MAPIStore.m @@ -24,6 +24,7 @@ #import #import +#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