From 5fbc499886e93f681f05b7219c7f844d17eaeb1d Mon Sep 17 00:00:00 2001 From: Lars Henriksen Date: Sun, 23 Jun 2019 21:42:24 +0200 Subject: Fix monthly and yearly recurrence algorithms The calculation of the year of the most recent occurrence for year dates before the start date (disregarding the year) is incorrect for frequencies greater than one. The most recent occurrence (for a date as mentioned) is either too far or too close in the past. In most cases it does no harm because the most recent ocurrence is in the past and does not span the date (i.e. there is no occurrence on the day). But the following appointment shows the presence of the bug: 12/31/2019 @ 12:00 -> 01/01/2020 @ 12:00 {2Y} |new year The occurence on 1 Jan 2020 is missing, because the most recent occurrence is too far in the past (31 Dec 2018 instead of 31 Dec 2019). An occurrence appears on 1 Jan 2021, because the most recent occurence is too close in the past (31 Dec 2020 instead of 31 Dec 2019). A similar miscalculation affects the monthly rule as proved by 3/31/2019 @ 12:00 -> 4/1/2019 @ 11:00 {2M} |change of month Signed-off-by: Lars Henriksen Signed-off-by: Lukas Fleischer --- src/recur.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/recur.c b/src/recur.c index fc1d538..1fd01ad 100644 --- a/src/recur.c +++ b/src/recur.c @@ -798,17 +798,18 @@ recur_item_find_occurrence(time_t item_start, long item_dur, break; case RECUR_MONTHLY: diff = diff_months(lt_item_day, lt_day) % rpt_freq; - if (lt_day.tm_mday < lt_item_day.tm_mday) - diff++; + if (!diff && lt_day.tm_mday < lt_item_day.tm_mday) + diff += rpt_freq; lt_item_day.tm_mon = lt_day.tm_mon - diff; lt_item_day.tm_year = lt_day.tm_year; break; case RECUR_YEARLY: diff = diff_years(lt_item_day, lt_day) % rpt_freq; - if (lt_day.tm_mon < lt_item_day.tm_mon || + if (!diff && + (lt_day.tm_mon < lt_item_day.tm_mon || (lt_day.tm_mon == lt_item_day.tm_mon && - lt_day.tm_mday < lt_item_day.tm_mday)) - diff++; + lt_day.tm_mday < lt_item_day.tm_mday))) + diff += rpt_freq; lt_item_day.tm_year = lt_day.tm_year - diff; break; default: -- cgit v1.2.3-70-g09d2