From 4139434f409f8b7b797411598aff5b761ed02489 Mon Sep 17 00:00:00 2001 From: Frederic Culot Date: Mon, 10 Dec 2007 19:03:23 +0000 Subject: bugfix in recur_item_inday(): leap years should now be properly handled --- src/recur.c | 101 ++++++++++++++++++++++++++++++------------------------------ 1 file changed, 50 insertions(+), 51 deletions(-) diff --git a/src/recur.c b/src/recur.c index 47db9f2..655cda8 100755 --- a/src/recur.c +++ b/src/recur.c @@ -1,4 +1,4 @@ -/* $calcurse: recur.c,v 1.30 2007/10/21 13:42:34 culot Exp $ */ +/* $calcurse: recur.c,v 1.31 2007/12/10 19:03:23 culot Exp $ */ /* * Calcurse - text-based organizer @@ -376,12 +376,9 @@ unsigned recur_item_inday(long item_start, struct days_s *item_exc, int rpt_type, int rpt_freq, long rpt_until, long day_start) { -#define YEARSTODAYS(x) ((x) * 365L + (x) / 4 - (x) / 100 + (x) / 400) - date_t start_date; - long day_end; - struct tm *lt; - int day_month, day_year, day_yday, day_mday, diff; + long day_end, diff; + struct tm lt_item, lt_day; struct days_s *exc; time_t t; char *error = @@ -389,12 +386,8 @@ recur_item_inday(long item_start, struct days_s *item_exc, day_end = day_start + DAYINSEC; t = day_start; - lt = localtime(&t); - day_month = lt->tm_mon; - day_year = lt->tm_year; - day_yday = lt->tm_yday; - day_mday = lt->tm_mday; - + lt_day = *localtime(&t); + for (exc = item_exc; exc != 0; exc = exc->next) if (exc->st < day_end && exc->st >= day_start) return 0; @@ -402,53 +395,59 @@ recur_item_inday(long item_start, struct days_s *item_exc, if (rpt_until == 0) /* we have an endless recurrent item */ rpt_until = day_end; - if (item_start > day_end || rpt_until < day_start) + if (item_start > day_end || rpt_until < day_start) return 0; t = item_start; - lt = localtime(&t); + lt_item = *localtime(&t); + + /* For proper calculation, both items must start at same time. */ + day_start += (lt_item.tm_hour * HOURINSEC + lt_item.tm_min * MININSEC + + lt_item.tm_sec); switch (rpt_type) { - case RECUR_DAILY: - diff = (YEARSTODAYS(lt->tm_year) + lt->tm_yday) - - (YEARSTODAYS(day_year) + day_yday); - if (diff % rpt_freq != 0) - return 0; - lt->tm_mday = day_mday; - lt->tm_mon = day_month; - lt->tm_year = day_year; - break; - case RECUR_WEEKLY: - diff = (YEARSTODAYS(lt->tm_year) + lt->tm_yday) - - (YEARSTODAYS(day_year) + day_yday); - if (diff % (rpt_freq*7) != 0) - return 0; - lt->tm_mday = day_mday; - lt->tm_mon = day_month; - lt->tm_year = day_year; - break; - case RECUR_MONTHLY: - diff = ((day_year - lt->tm_year) * 12) + - (day_month - lt->tm_mon); - if (diff % rpt_freq != 0) - return 0; - lt->tm_mon = day_month; - lt->tm_year = day_year; - break; - case RECUR_YEARLY: - diff = day_year - lt->tm_year; + case RECUR_DAILY: + diff = (long)difftime((time_t)day_start, (time_t)item_start); + if (diff % (rpt_freq * DAYINSEC) != 0) + return 0; + lt_item.tm_mday = lt_day.tm_mday; + lt_item.tm_mon = lt_day.tm_mon; + lt_item.tm_year = lt_day.tm_year; + break; + case RECUR_WEEKLY: + if (lt_item.tm_wday != lt_day.tm_wday) + return 0; + else { + diff = ((lt_day.tm_yday - lt_item.tm_yday) / WEEKINDAYS); if (diff % rpt_freq != 0) return 0; - lt->tm_year = day_year; - break; - default: - fputs(error, stderr); - exit(EXIT_FAILURE); + } + lt_item.tm_mday = lt_day.tm_mday; + lt_item.tm_mon = lt_day.tm_mon; + lt_item.tm_year = lt_day.tm_year; + break; + case RECUR_MONTHLY: + diff = ((lt_day.tm_year - lt_item.tm_year) * 12) + + (lt_day.tm_mon - lt_item.tm_mon); + if (diff % rpt_freq != 0) + return 0; + lt_item.tm_mon = lt_day.tm_mon; + lt_item.tm_year = lt_day.tm_year; + break; + case RECUR_YEARLY: + diff = lt_day.tm_year - lt_item.tm_year; + if (diff % rpt_freq != 0) + return 0; + lt_item.tm_year = lt_day.tm_year; + break; + default: + fputs(error, stderr); + exit(EXIT_FAILURE); } - start_date.dd = lt->tm_mday; - start_date.mm = lt->tm_mon + 1; - start_date.yyyy = lt->tm_year + 1900; - item_start = date2sec(start_date, lt->tm_hour, lt->tm_min); + start_date.dd = lt_item.tm_mday; + start_date.mm = lt_item.tm_mon + 1; + start_date.yyyy = lt_item.tm_year + 1900; + item_start = date2sec(start_date, lt_item.tm_hour, lt_item.tm_min); if (item_start < day_end && item_start >= day_start) return item_start; -- cgit v1.2.3-54-g00ecf