summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKen Murchison <murch@fastmail.com>2020-11-06 09:23:00 -0500
committerKen Murchison <murch@fastmail.com>2020-11-08 09:24:03 -0500
commit6c6944d917c897f48e43f9e5ea718217aacf0c1d (patch)
treedb151b1d7c8e39d7fea06f3a61a3a111756e17bc
parent0fa0bd20b158842d48ba538dcd011b07f97fdefb (diff)
downloadlibical-git-6c6944d917c897f48e43f9e5ea718217aacf0c1d.tar.gz
icalrecur.c: fixed handling of BYWEEKNO=1 with BYDAY (added tests for first and last weeks)
-rw-r--r--src/libical/icalrecur.c41
-rw-r--r--src/test/icalrecur_test.c10
-rw-r--r--src/test/icalrecur_test.out8
3 files changed, 51 insertions, 8 deletions
diff --git a/src/libical/icalrecur.c b/src/libical/icalrecur.c
index 1437198f..c1f960e6 100644
--- a/src/libical/icalrecur.c
+++ b/src/libical/icalrecur.c
@@ -2329,8 +2329,11 @@ static int expand_by_day(icalrecur_iterator *impl, int year,
}
}
- (void)__icaltime_from_day_of_year(impl, day + doy_offset, year,
- &this_weekno);
+ if (doy_offset < 0) this_weekno = 1;
+ else {
+ (void)__icaltime_from_day_of_year(impl, day + doy_offset, year,
+ &this_weekno);
+ }
/* Add instance(s) of the weekday within the period */
do {
@@ -2671,15 +2674,37 @@ static int expand_year_days(icalrecur_iterator *impl, int year)
}
} else {
/* Numeric BYDAY are within the year */
+ short doy_offset = 0, last_day;
+
+ if (has_by_data(impl, BY_WEEK_NO)) {
+ int weekno;
+
+ /* See which week contains Jan 1 */
+ (void)__icaltime_from_day_of_year(impl, 1, year, &weekno);
+ if (weekno > 1) {
+ /* Jan 1 is in last week of previous year - jump ahead */
+ doy_offset += 7;
+ }
- /* Get day of week of first day of year */
- (void)get_day_of_year(impl, year, 1, 1, &first_dow);
+ /* Set start and end of ISO week-numbering year */
+ doy_offset += get_start_of_week(impl) - 1;
+ last_day = (7 * weeks_in_year(year));
- /* Get day of week of last day of year */
- set_day_of_year(impl, days_in_year);
- last_dow = get_day_of_week(impl);
+ first_dow = impl->rule.week_start;
+ last_dow = (first_dow + 6) % 7;
+ }
+ else {
+ /* Get day of week of first day of year */
+ (void)get_day_of_year(impl, year, 1, 1, &first_dow);
+
+ /* Get day of week of last day of year */
+ set_day_of_year(impl, days_in_year);
+ last_dow = get_day_of_week(impl);
+
+ last_day = days_in_year;
+ }
- set_pos_total += expand_by_day(impl, year, 0, days_in_year,
+ set_pos_total += expand_by_day(impl, year, doy_offset, last_day,
first_dow, last_dow, limiting);
}
}
diff --git a/src/test/icalrecur_test.c b/src/test/icalrecur_test.c
index 7043cb3d..06c4078a 100644
--- a/src/test/icalrecur_test.c
+++ b/src/test/icalrecur_test.c
@@ -390,6 +390,16 @@ const struct recur rfc5545[] = {
"FREQ=WEEKLY;BYDAY=WE,FR;INTERVAL=2;COUNT=4",
NULL},
+ /* First 2 and last 2 ISO weeks of the year on Tue */
+ {"20130101T000000",
+ "FREQ=YEARLY;BYWEEKNO=1,2,-1,-2;BYDAY=TU;UNTIL=20170101T000000Z",
+ NULL},
+
+ /* 53rd ISO week of the year on Tue and Sat */
+ {"20130101T000000",
+ "FREQ=YEARLY;BYWEEKNO=53;BYDAY=TU,SA;UNTIL=20170101T000000Z",
+ NULL},
+
{NULL, NULL, NULL}
};
diff --git a/src/test/icalrecur_test.out b/src/test/icalrecur_test.out
index c08a19eb..4e3d03bc 100644
--- a/src/test/icalrecur_test.out
+++ b/src/test/icalrecur_test.out
@@ -272,3 +272,11 @@ INSTANCES:20130512T000000,20260512T000000,20390512T000000
RRULE:FREQ=WEEKLY;BYDAY=WE,FR;INTERVAL=2;COUNT=4
DTSTART:20190101T100000
INSTANCES:20190102T100000,20190104T100000,20190116T100000,20190118T100000
+
+RRULE:FREQ=YEARLY;BYWEEKNO=1,2,-1,-2;BYDAY=TU;UNTIL=20170101T000000Z
+DTSTART:20130101T000000
+INSTANCES:20130101T000000,20130108T000000,20131217T000000,20131224T000000,20131231T000000,20140107T000000,20141216T000000,20141223T000000,20141230T000000,20150106T000000,20151222T000000,20151229T000000,20160105T000000,20160112T000000,20161220T000000,20161227T000000
+
+RRULE:FREQ=YEARLY;BYWEEKNO=53;BYDAY=TU,SA;UNTIL=20170101T000000Z
+DTSTART:20130101T000000
+INSTANCES:20151229T000000,20160102T000000