diff --git a/ChangeLog b/ChangeLog index 0899f24ff..2c14b1ac4 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,9 @@ 2010-03-22 Wolfgang Sourdeau + * Tests/Unit/TestiCalTimeZonePeriod.m: new test module for + iCalTimeZonePeriod. Added full test method for + _occurenceForDate:byRRule:. + * Tests/Unit/SOGoTestRunner.m (-init): messages must be initialized to a mutable array. diff --git a/SOPE/NGCards/ChangeLog b/SOPE/NGCards/ChangeLog index a6663c5df..fb4d15e83 100644 --- a/SOPE/NGCards/ChangeLog +++ b/SOPE/NGCards/ChangeLog @@ -1,3 +1,9 @@ +2010-03-22 Wolfgang Sourdeau + + * iCalTimeZonePeriod.m (_occurenceForDate:byRRule:): fixed + computing of timezone switch dates for periods starting at a + "negative" day of the month. + 2010-03-09 Wolfgang Sourdeau * iCalTimeZone.m (-periodForDate:): the order in which daylight diff --git a/SOPE/NGCards/iCalTimeZonePeriod.m b/SOPE/NGCards/iCalTimeZonePeriod.m index f1f7a0a04..69651dc97 100644 --- a/SOPE/NGCards/iCalTimeZonePeriod.m +++ b/SOPE/NGCards/iCalTimeZonePeriod.m @@ -134,6 +134,14 @@ second: -[self _secondsOfOffset: @"tzoffsetfrom"]]; dateDayOfWeek = [tmpDate dayOfWeek]; + + /* If the day of the time change is "-XSU", we need to determine whether the + first day of next month is in the same week. In practice, as most time + changes occurs on sundays, it will be false only when that first day is a + sunday, but we want to remain algorithmically exact. */ + if (dateDayOfWeek > dayOfWeek && pos < 0) + pos++; + offset = (dayOfWeek - dateDayOfWeek) + (pos * 7); tmpDate = [tmpDate addYear: 0 month: 0 day: offset hour: 0 minute: 0 second: 0]; diff --git a/Tests/Unit/GNUmakefile b/Tests/Unit/GNUmakefile index 321c3c0bc..6439fd442 100644 --- a/Tests/Unit/GNUmakefile +++ b/Tests/Unit/GNUmakefile @@ -14,6 +14,8 @@ $(TEST_TOOL)_OBJC_FILES += \ SOGoTest.m \ SOGoTestRunner.m \ \ + TestiCalTimeZonePeriod.m \ + \ TestBSJSONAdditions.m TOOL_NAME = $(TEST_TOOL) diff --git a/Tests/Unit/TestiCalTimeZonePeriod.m b/Tests/Unit/TestiCalTimeZonePeriod.m new file mode 100644 index 000000000..09657ea9c --- /dev/null +++ b/Tests/Unit/TestiCalTimeZonePeriod.m @@ -0,0 +1,117 @@ +/* TestiCalTimeZonePeriod.m - this file is part of SOGo + * + * Copyright (C) 2010 Inverse inc. + * + * Author: Wolfgang Sourdeau + * + * 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 + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This file is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#import + +#import + +#import +#import +#import + +#import "SOGoTest.h" + +@interface iCalTimeZonePeriod (private) + +- (NSCalendarDate *) _occurenceForDate: (NSCalendarDate *) refDate + byRRule: (iCalRecurrenceRule *) rrule; + +@end + +@interface TestiCalTimeZonePeriod : SOGoTest +@end + +@implementation TestiCalTimeZonePeriod + +- (void) test__occurenceForDate_byRRule_ +{ + /* all rules are happening on 2010-03-14 */ + NSString *periods[] = { @"20100307T120000Z", + (@"BEGIN:DAYLIGHT\r\n" + @"TZOFFSETFROM:+0100\r\n" + @"TZOFFSETTO:+0200\r\n" + @"TZNAME:CEST\r\n" + @"DTSTART:20040307T020000\r\n" + @"RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=1SU\r\n" + @"END:DAYLIGHT\r\n"), + @"20100314T120000Z", + (@"BEGIN:DAYLIGHT\r\n" + @"TZOFFSETFROM:+0100\r\n" + @"TZOFFSETTO:+0200\r\n" + @"TZNAME:CEST\r\n" + @"DTSTART:20040314T020000\r\n" + @"RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=2SU\r\n" + @"END:DAYLIGHT\r\n"), + @"20100314T120000Z", + (@"BEGIN:DAYLIGHT\r\n" + @"TZOFFSETFROM:+0100\r\n" + @"TZOFFSETTO:+0200\r\n" + @"TZNAME:CEST\r\n" + @"DTSTART:20040314T020000\r\n" + @"RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=-3SU\r\n" + @"END:DAYLIGHT\r\n"), + @"20100328T120000Z", + (@"BEGIN:DAYLIGHT\r\n" + @"TZOFFSETFROM:+0100\r\n" + @"TZOFFSETTO:+0200\r\n" + @"TZNAME:CEST\r\n" + @"DTSTART:20040328T020000\r\n" + @"RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU\r\n" + @"END:DAYLIGHT\r\n"), + NULL }; + NSString *dates[] = { @"20100201T120000Z", /* far before */ + @"20100225T120000Z", /* at least one week before */ + @"20100303T120000Z", /* less than one week before */ + @"20100314T120000Z", /* the day of the time change */ + @"20100315T120000Z", /* the next day */ + @"20100318T120000Z", /* less than one week after */ + @"20100323T120000Z", /* more than one week after */ + @"20100501T120000Z", /* far after */ + NULL }; + NSString **currentTCDate, **currentPeriod, **currentDate, *error; + iCalTimeZonePeriod *testPeriod; + NSCalendarDate *timeChangeDate, *testDate, *resultDate; + + currentTCDate = periods; + currentPeriod = periods + 1; + while (*currentTCDate) + { + timeChangeDate = [*currentTCDate asCalendarDate]; /* "expected result" */ + testPeriod = [iCalTimeZonePeriod parseSingleFromSource: *currentPeriod]; + currentDate = dates; + while (*currentDate) + { + testDate = [*currentDate asCalendarDate]; + resultDate = [testPeriod _occurenceForDate: testDate + byRRule: (iCalRecurrenceRule *) [testPeriod uniqueChildWithTag: @"rrule"]]; + + error = [NSString stringWithFormat: @"time change date for date '%@' does not occur on expected date (result: %@, exp.: %@)", + *currentDate, resultDate, timeChangeDate]; + testWithMessage([timeChangeDate isDateOnSameDay: resultDate], error); + currentDate++; + } + currentPeriod += 2; + currentTCDate += 2; + } +} + +@end