From b2321a7567340ff285cfcde5f9b4c7e60be7374d Mon Sep 17 00:00:00 2001 From: Frederic Culot Date: Mon, 8 Mar 2010 08:44:28 +0000 Subject: Patch to correct the wrong calculation of recurrent items' dates after a turn of year (submitted by Lukas Fleischer, thanks!). --- ChangeLog | 11 ++++++++ src/calendar.c | 5 ++-- src/calendar.h | 12 +++++++-- src/recur.c | 81 +++++++++++++++++++++++++++++++++++++++++++++++++++++----- src/vars.h | 9 ++----- 5 files changed, 99 insertions(+), 19 deletions(-) diff --git a/ChangeLog b/ChangeLog index 55124ca..cf1e341 100755 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,14 @@ +2010-03-08 Frederic Culot + + * src/recur.c (diff_days, diff_weeks, diff_months, diff_years): + new functions provided by Lukas Fleischer + * src/recur.c (recur_item_inday): patch provided by Lukas + Fleischer to correct the wrong calculation of recurrent dates + after a turn of years + + * src/calendar.h: defines related to dates moved from calendar.c + and vars.h + 2010-03-01 Frederic Culot * src/calendar.c (calendar_date_thread): avoid compilation diff --git a/src/calendar.c b/src/calendar.c index 2c6c781..2be7c62 100755 --- a/src/calendar.c +++ b/src/calendar.c @@ -1,9 +1,9 @@ -/* $calcurse: calendar.c,v 1.31 2010/03/01 18:55:45 culot Exp $ */ +/* $calcurse: calendar.c,v 1.32 2010/03/08 08:44:44 culot Exp $ */ /* * Calcurse - text-based organizer * - * Copyright (c) 2004-2009 Frederic Culot + * Copyright (c) 2004-2010 Frederic Culot * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -64,7 +64,6 @@ #define lzero 318.351648 /* lunar mean long at EPOCH */ #define Pzero 36.340410 /* lunar mean long of perigee at EPOCH */ #define Nzero 318.510107 /* lunar mean long of node at EPOCH */ -#define TM_YEAR_BASE 1900 #define isleap(y) ((((y) % 4) == 0 && ((y) % 100) != 0) || ((y) % 400) == 0) diff --git a/src/calendar.h b/src/calendar.h index 60499a7..e900bcd 100755 --- a/src/calendar.h +++ b/src/calendar.h @@ -1,9 +1,9 @@ -/* $calcurse: calendar.h,v 1.18 2009/10/28 15:15:43 culot Exp $ */ +/* $calcurse: calendar.h,v 1.19 2010/03/08 08:44:44 culot Exp $ */ /* * Calcurse - text-based organizer * - * Copyright (c) 2004-2009 Frederic Culot + * Copyright (c) 2004-2010 Frederic Culot * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -60,6 +60,14 @@ #define CALHEIGHT 12 #define CALWIDTH 30 +#define DAYINSEC 86400 +#define HOURINSEC 3600 +#define MININSEC 60 +#define YEARINDAYS 365 +#define YEARINMONTHS 12 +#define WEEKINDAYS 7 +#define TM_YEAR_BASE 1900 + typedef enum { /* days of week */ SUNDAY, diff --git a/src/recur.c b/src/recur.c index e21bf0c..5d06726 100755 --- a/src/recur.c +++ b/src/recur.c @@ -1,9 +1,9 @@ -/* $calcurse: recur.c,v 1.52 2009/07/19 08:20:01 culot Exp $ */ +/* $calcurse: recur.c,v 1.53 2010/03/08 08:44:44 culot Exp $ */ /* * Calcurse - text-based organizer * - * Copyright (c) 2004-2009 Frederic Culot + * Copyright (c) 2004-2010 Frederic Culot * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -55,6 +55,7 @@ struct recur_event_s *recur_elist; static struct recur_event_s bkp_cut_recur_event; static recur_apoint_llist_node_t bkp_cut_recur_apoint; + static void free_exc (struct days_s *exc) { @@ -589,11 +590,78 @@ recur_save_data (FILE *f) pthread_mutex_unlock (&(recur_alist_p->mutex)); } + +/* + * The two following defines together with the diff_days, diff_weeks, + * diff_months and diff_years functions were provided by Lukas Fleischer to + * correct the wrong calculation of recurrent dates after a turn of year. + */ +#define bc(start, end, bs) \ + (((end) - (start) + ((start) % bs) - ((end) % bs)) / bs \ + + ((((start) % bs) == 0) ? 1 : 0)) + +#define leapcount(start, end) \ + (bc(start, end, 4) - bc(start, end, 100) + bc(start, end, 400)) + + +/* Calculate the difference in days between two dates. */ +static long +diff_days (struct tm lt_start, struct tm lt_end) +{ + long diff; + + if (lt_end.tm_year < lt_start.tm_year) + return 0; + + diff = lt_end.tm_yday - lt_start.tm_yday; + + if (lt_end.tm_year > lt_start.tm_year) + { + diff += (lt_end.tm_year - lt_start.tm_year) * YEARINDAYS; + diff += leapcount (lt_start.tm_year + TM_YEAR_BASE, + lt_end.tm_year + TM_YEAR_BASE - 1); + } + + return diff; +} + +/* Calculate the difference in weeks between two dates. */ +static long +diff_weeks (struct tm lt_start, struct tm lt_end) +{ + return diff_days (lt_start, lt_end) / WEEKINDAYS; +} + +/* Calculate the difference in months between two dates. */ +static long +diff_months (struct tm lt_start, struct tm lt_end) +{ + long diff; + + if (lt_end.tm_year < lt_start.tm_year) + return 0; + + diff = lt_end.tm_mon - lt_start.tm_mon; + diff += (lt_end.tm_year - lt_start.tm_year) * YEARINMONTHS; + + return diff; +} + +/* Calculate the difference in years between two dates. */ +static long +diff_years (struct tm lt_start, struct tm lt_end) +{ + return lt_end.tm_year - lt_start.tm_year; +} + /* * Check if the recurrent item belongs to the selected day, * and if yes, return the real start time. + * * This function was improved thanks to Tony's patch. * Thanks also to youshe for reporting daylight saving time related problems. + * And finally thanks to Lukas for providing a patch to correct the wrong + * calculation of recurrent dates after a turn of years. */ unsigned recur_item_inday (long item_start, struct days_s *item_exc, int rpt_type, @@ -625,7 +693,7 @@ recur_item_inday (long item_start, struct days_s *item_exc, int rpt_type, switch (rpt_type) { case RECUR_DAILY: - diff = lt_day.tm_yday - lt_item.tm_yday; + diff = diff_days (lt_item, lt_day); if (diff % rpt_freq != 0) return (0); lt_item.tm_mday = lt_day.tm_mday; @@ -637,7 +705,7 @@ recur_item_inday (long item_start, struct days_s *item_exc, int rpt_type, return (0); else { - diff = ((lt_day.tm_yday - lt_item.tm_yday) / WEEKINDAYS); + diff = diff_weeks (lt_item, lt_day); if (diff % rpt_freq != 0) return (0); } @@ -646,15 +714,14 @@ recur_item_inday (long item_start, struct days_s *item_exc, int rpt_type, 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)); + diff = diff_months (lt_item, lt_day); 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; + diff = diff_years (lt_item, lt_day); if (diff % rpt_freq != 0) return (0); lt_item.tm_year = lt_day.tm_year; diff --git a/src/vars.h b/src/vars.h index 7f45c98..fbb88c1 100755 --- a/src/vars.h +++ b/src/vars.h @@ -1,9 +1,9 @@ -/* $calcurse: vars.h,v 1.37 2009/08/01 13:31:21 culot Exp $ */ +/* $calcurse: vars.h,v 1.38 2010/03/08 08:44:44 culot Exp $ */ /* * Calcurse - text-based organizer * - * Copyright (c) 2004-2009 Frederic Culot + * Copyright (c) 2004-2010 Frederic Culot * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -82,11 +82,6 @@ #define ATTR_HIGH 5 #define ATTR_HIGHEST 6 -#define DAYINSEC 86400 -#define HOURINSEC 3600 -#define MININSEC 60 -#define WEEKINDAYS 7 - #define STATUSHEIGHT 2 #define NOTESIZ 6 -- cgit v1.2.3