(fix) handle flattened timezone definitions (fixes #2690)
parent
658cb956d9
commit
f607cb03c5
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue