X-Git-Url: https://diplodocus.org/git/nmh/blobdiff_plain/bfff2c60b2c860c2bc466bdab94daf770d86aec5..4d5d51e903a42c23800540930244448c4aacae16:/sbr/datetime.c diff --git a/sbr/datetime.c b/sbr/datetime.c index f79c9424..cdcb8991 100644 --- a/sbr/datetime.c +++ b/sbr/datetime.c @@ -6,9 +6,11 @@ */ #include "h/mh.h" +#include "dtime.h" #include "error.h" #include "h/icalendar.h" -#include +#include "datetime.h" +#include "h/fmt_scan.h" #include "h/tws.h" #include "h/utils.h" #include "unquote.h" @@ -272,7 +274,7 @@ free_timezones (tzdesc_t timezone) * Given a recurrence rule and year, calculate its time in seconds * from 01 January UTC of the year. */ -time_t +static time_t rrule_clock (const char *rrule, const char *starttime, const char *zone, unsigned int year) { @@ -286,14 +288,15 @@ rrule_clock (const char *rrule, const char *starttime, const char *zone, int specific_day = 1; /* BYDAY integer (prefix) */ char buf[32]; int day; + int end_of_week; if ((cp = nmh_strcasestr (rrule, "BYDAY="))) { cp += 6; /* BYDAY integers must be ASCII. */ - if (*cp == '+') { ++cp; } /* +n specific day; don't support '-' */ - else if (*cp == '-') { goto fail; } + if (*cp == '+') { ++cp; } /* +n specific day */ + else if (*cp == '-') { ++cp; specific_day = -1; } - if (isdigit ((unsigned char) *cp)) { specific_day = *cp++ - 0x30; } + if (isdigit ((unsigned char) *cp)) { specific_day *= *cp++ - 0x30; } if (! strncasecmp (cp, "SU", 2)) { wday = 0; } else if (! strncasecmp (cp, "MO", 2)) { wday = 1; } @@ -307,12 +310,13 @@ rrule_clock (const char *rrule, const char *starttime, const char *zone, month = atoi (cp + 8); } - for (day = 1; day <= 7; ++day) { + end_of_week = specific_day > 0 ? 7 * specific_day : + dmlastday(year, month) + 7 * (1 + specific_day); + for (day = end_of_week - 6; day <= end_of_week; ++day) { /* E.g, 11-01-2014 02:00:00-0400 */ snprintf (buf, sizeof buf, "%02d-%02d-%04u %.2s:%.2s:%.2s%s", - month, day + 7 * (specific_day-1), year, - starttime, starttime + 2, starttime + 4, - zone ? zone : "0000"); + month, day, year, starttime, starttime + 2, + starttime + 4, zone ? zone : "0000"); if ((tws = dparsetime (buf))) { if (! (tws->tw_flags & (TW_SEXP|TW_SIMP))) { set_dotw (tws); } @@ -323,15 +327,14 @@ rrule_clock (const char *rrule, const char *starttime, const char *zone, } } - if (day <= 7) { + if (day <= end_of_week) { clock = tws->tw_clock; } } -fail: if (clock == 0) { inform("Unsupported RRULE format: %s, assume local timezone, continuing...", - rrule); + rrule); } return clock;