(fix) handle flattened timezone definitions (fixes #2690)

pull/214/head
Ludovic Marcotte 2016-06-09 15:01:35 -04:00
parent 658cb956d9
commit f607cb03c5
2 changed files with 78 additions and 18 deletions

View File

@ -183,29 +183,44 @@ static NSArray *knownTimeZones;
return [[self uniqueChildWithTag: @"tzid"] flattenedValuesForKey: @""]; return [[self uniqueChildWithTag: @"tzid"] flattenedValuesForKey: @""];
} }
- (NSCalendarDate *) _occurrenceForPeriodNamed: (NSString *) pName - (NSDictionary *) _occurrenceForPeriodNamed: (NSString *) pName
forDate: (NSCalendarDate *) aDate forDate: (NSCalendarDate *) aDate
{ {
NSArray *periods; NSArray *periods;
NSEnumerator *periodsList; NSEnumerator *periodsList;
iCalTimeZonePeriod *period; iCalTimeZonePeriod *period;
NSCalendarDate *occurrence; NSCalendarDate *occurrence;
NSDictionary *periodDict;
occurrence = nil; occurrence = nil;
periodDict = nil;
periods = [[self childrenWithTag: pName] periods = [[self childrenWithTag: pName]
sortedArrayUsingSelector: @selector (compare:)]; sortedArrayUsingSelector: @selector (compare:)];
periodsList = [periods reverseObjectEnumerator]; periodsList = [periods reverseObjectEnumerator];
while (!occurrence while ((period = (iCalTimeZonePeriod *) [periodsList nextObject]))
&& (period = (iCalTimeZonePeriod *) [periodsList nextObject])) {
occurrence = [period occurrenceForDate: aDate]; if ([periods count] > 1 && ([[period startDate] yearOfCommonEra] > [aDate yearOfCommonEra]))
continue;
return occurrence; occurrence = [period occurrenceForDate: aDate];
if (occurrence && (!periodDict || [occurrence earlierDate: [periodDict objectForKey: @"occurrence"]] == [periodDict objectForKey: @"occurrence"]))
{
periodDict = [NSDictionary dictionaryWithObjectsAndKeys:
period, @"period",
occurrence, @"occurrence",nil];
occurrence = nil;
}
}
return periodDict;
} }
- (iCalTimeZonePeriod *) periodForDate: (NSCalendarDate *) date - (iCalTimeZonePeriod *) periodForDate: (NSCalendarDate *) date
{ {
NSCalendarDate *daylightOccurence, *standardOccurence; //NSCalendarDate *daylightOccurence, *standardOccurence;
NSDictionary *daylightOccurence, *standardOccurence;
iCalTimeZonePeriod *period; iCalTimeZonePeriod *period;
/* FIXME, this could cause crashes when timezones are not properly /* FIXME, this could cause crashes when timezones are not properly
@ -213,30 +228,33 @@ static NSArray *knownTimeZones;
daylightOccurence = [self _occurrenceForPeriodNamed: @"daylight" daylightOccurence = [self _occurrenceForPeriodNamed: @"daylight"
forDate: date]; forDate: date];
standardOccurence = [self _occurrenceForPeriodNamed: @"standard" standardOccurence = [self _occurrenceForPeriodNamed: @"standard"
forDate: date]; forDate: date];
if (!standardOccurence) if (!standardOccurence && !daylightOccurence)
period = (iCalTimeZonePeriod *) [self uniqueChildWithTag: @"standard"];
else if (!standardOccurence)
period = (iCalTimeZonePeriod *) [self uniqueChildWithTag: @"daylight"]; period = (iCalTimeZonePeriod *) [self uniqueChildWithTag: @"daylight"];
else if (!daylightOccurence) else if (!daylightOccurence)
period = (iCalTimeZonePeriod *) [self uniqueChildWithTag: @"standard"]; period = (iCalTimeZonePeriod *) [self uniqueChildWithTag: @"standard"];
else if ([date earlierDate: daylightOccurence] == date) else if ([date earlierDate: [daylightOccurence objectForKey: @"occurrence"]] == date)
{ {
if ([date earlierDate: standardOccurence] == date if ([date earlierDate: [standardOccurence objectForKey: @"occurrence"]] == date
&& ([standardOccurence earlierDate: daylightOccurence] && ([[standardOccurence objectForKey: @"occurrence"] earlierDate: [daylightOccurence objectForKey: @"occurrence"]]
== standardOccurence)) == [standardOccurence objectForKey: @"occurrence"]))
period = (iCalTimeZonePeriod *) [self uniqueChildWithTag: @"daylight"]; period = (iCalTimeZonePeriod *) [daylightOccurence objectForKey: @"period"];
else else
period = (iCalTimeZonePeriod *) [self uniqueChildWithTag: @"standard"]; period = (iCalTimeZonePeriod *) [standardOccurence objectForKey: @"period"];
} }
else else
{ {
if ([standardOccurence earlierDate: date] == standardOccurence if ([[standardOccurence objectForKey: @"occurrence"] earlierDate: date] == [standardOccurence objectForKey: @"occurrence"]
&& ([daylightOccurence earlierDate: standardOccurence] && ([[daylightOccurence objectForKey: @"occurrence"] earlierDate: [standardOccurence objectForKey: @"occurrence"]]
== daylightOccurence)) == [daylightOccurence objectForKey: @"occurrence"] ))
period = (iCalTimeZonePeriod *) [self uniqueChildWithTag: @"standard"]; period = (iCalTimeZonePeriod *) [standardOccurence objectForKey: @"period"];
else else
period = (iCalTimeZonePeriod *) [self uniqueChildWithTag: @"daylight"]; period = (iCalTimeZonePeriod *) [daylightOccurence objectForKey: @"period"];
} }
return period; return period;

View File

@ -37,6 +37,8 @@
if ([classTag isEqualToString: @"RRULE"]) if ([classTag isEqualToString: @"RRULE"])
tagClass = [iCalRecurrenceRule class]; tagClass = [iCalRecurrenceRule class];
else if ([classTag isEqualToString: @"RDATE"])
tagClass = [iCalDateTime class];
else if ([classTag isEqualToString: @"DTSTART"]) else if ([classTag isEqualToString: @"DTSTART"])
tagClass = [iCalDateTime class]; tagClass = [iCalDateTime class];
else if ([classTag isEqualToString: @"TZOFFSETFROM"] else if ([classTag isEqualToString: @"TZOFFSETFROM"]
@ -247,19 +249,59 @@
return tmpDate; return tmpDate;
} }
- (NSCalendarDate *) _occurrenceFromRdate: (NSCalendarDate *) refDate
rDates: (NSArray *) rDatesIn;
{
NSArray *rDates;
NSEnumerator *dateList;
NSCalendarDate *rDateCur, *rDateOut;
NSString *dateString;
unsigned i;
rDateCur = nil;
rDateOut = nil;
dateList = [rDatesIn objectEnumerator];
while ((dateString = [dateList nextObject]))
{
rDates = [(iCalDateTime*) dateString dateTimes];
for (i = 0; i < [rDates count]; i++)
{
rDateCur = [rDates objectAtIndex: i];
if (!rDateOut || ([rDateCur yearOfCommonEra] > [rDateOut yearOfCommonEra] && [refDate yearOfCommonEra] >= [rDateCur yearOfCommonEra]))
rDateOut = rDateCur;
}
}
return rDateOut;
}
- (NSCalendarDate *) occurrenceForDate: (NSCalendarDate *) refDate; - (NSCalendarDate *) occurrenceForDate: (NSCalendarDate *) refDate;
{ {
NSCalendarDate *tmpDate; NSCalendarDate *tmpDate;
iCalRecurrenceRule *rrule; iCalRecurrenceRule *rrule;
NSArray *rDates;
tmpDate = nil; tmpDate = nil;
rrule = (iCalRecurrenceRule *) [self uniqueChildWithTag: @"rrule"]; rrule = (iCalRecurrenceRule *) [self uniqueChildWithTag: @"rrule"];
rDates = (NSArray *) [self childrenWithTag: @"rdate"];
if ([rDates count])
{
tmpDate = [self _occurrenceFromRdate: refDate rDates: rDates];
return tmpDate;
}
if ([rrule isVoid]) if ([rrule isVoid])
tmpDate tmpDate
= [(iCalDateTime *) [self uniqueChildWithTag: @"dtstart"] dateTime]; = [(iCalDateTime *) [self uniqueChildWithTag: @"dtstart"] dateTime];
else if ([rrule untilDate] == nil || [refDate compare: [rrule untilDate]] == NSOrderedAscending) else if ([rrule untilDate] == nil || [refDate compare: [rrule untilDate]] == NSOrderedAscending)
tmpDate = [self _occurrenceForDate: refDate byRRule: rrule]; tmpDate = [self _occurrenceForDate: refDate byRRule: rrule];
else if ([refDate compare: [rrule untilDate]] == NSOrderedDescending)
tmpDate = [rrule untilDate];
return tmpDate; return tmpDate;
} }