aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--CHANGES.md31
-rwxr-xr-xbuild-aux/git-version-gen2
-rwxr-xr-xcontrib/caldav/calcurse-caldav.py42
-rw-r--r--doc/calcurse.1.txt6
-rw-r--r--doc/manual.txt2
-rw-r--r--doc/repeat.txt170
-rw-r--r--src/apoint.c21
-rw-r--r--src/calcurse.c50
-rw-r--r--src/calcurse.h102
-rw-r--r--src/day.c2
-rw-r--r--src/event.c18
-rw-r--r--src/ical.c635
-rw-r--r--src/io.c138
-rw-r--r--src/note.c7
-rw-r--r--src/notify.c9
-rw-r--r--src/pcal.c10
-rw-r--r--src/recur.c1111
-rw-r--r--src/ui-day.c754
-rw-r--r--src/utils.c58
-rw-r--r--test/Makefile.am7
-rw-r--r--test/data/ical-009.ical48
-rw-r--r--test/data/ical-012.ical93
-rw-r--r--test/data/rfc554528
-rwxr-xr-xtest/ical-009.sh31
-rwxr-xr-xtest/ical-012.sh76
-rwxr-xr-xtest/recur-009.sh5342
-rwxr-xr-xtest/recur-010.sh51
27 files changed, 8086 insertions, 758 deletions
diff --git a/CHANGES.md b/CHANGES.md
index 70a4d2a..263cf83 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -1,6 +1,37 @@
Release Notes
=============
+Version 4.6.0 (2020-03-27)
+--------------------------
+
+- New features:
+
+ * XDG base directory support: While using ~/.calcurse/ is still supported
+ for backwards compatibility, we recommend putting your configuration
+ files in ~/.config/calcurse/ and your data files in
+ ~/.local/share/calcurse/ instead (implemented by Nitroretro).
+
+ * Configurable text for empty days (implemented by Lars Henriksen).
+
+ * Support RET to set the todo item priority to 0 (implemented by Issam
+ Maghni).
+
+ * Various improvements in iCal imports (implemented by Lars Henriksen).
+
+- New calcurse-caldav features:
+
+ * Documentation for Yahoo's Calendar Server.
+
+- Bug fixes:
+
+ * Escape necessary characters in SUMMARY on export (implemented by Kelvin
+ Jackson).
+
+ * Update notification bar properly when certain recurrent appointments are
+ deleted (implemented by Lars Henriksen).
+
+ * Fix save of interactively imported data (implemented by Lars Henriksen).
+
Version 4.5.1 (2019-10-18)
--------------------------
diff --git a/build-aux/git-version-gen b/build-aux/git-version-gen
index 67e4839..31209e2 100755
--- a/build-aux/git-version-gen
+++ b/build-aux/git-version-gen
@@ -6,7 +6,7 @@ then
exit 1
fi
-DEF_VER=4.5.1
+DEF_VER=4.6.0
VERFILE="$1"
if [ -d '.git' ]
diff --git a/contrib/caldav/calcurse-caldav.py b/contrib/caldav/calcurse-caldav.py
index beea376..7c9b89b 100755
--- a/contrib/caldav/calcurse-caldav.py
+++ b/contrib/caldav/calcurse-caldav.py
@@ -4,6 +4,7 @@ import argparse
import base64
import configparser
import httplib2
+import pathlib
import os
import re
import subprocess
@@ -37,9 +38,10 @@ def die(msg):
def check_dir(dir):
- if not os.path.isdir(dir):
- die("invalid directory: {0}".format(dir))
-
+ try:
+ pathlib.Path(dir).mkdir(parents=True, exist_ok=True)
+ except FileExistsError:
+ die("{} is not a directory".format(dir))
def die_atnode(msg, node):
if debug:
@@ -520,20 +522,28 @@ nsmap = {"D": "DAV:", "C": "urn:ietf:params:xml:ns:caldav"}
# Initialize default values.
if os.path.isdir(os.path.expanduser("~/.calcurse")):
- configfn = os.path.expanduser("~/.calcurse/caldav/config")
- lockfn = os.path.expanduser("~/.calcurse/caldav/lock")
- syncdbfn = os.path.expanduser("~/.calcurse/caldav/sync.db")
- hookdir = os.path.expanduser("~/.calcurse/caldav/hooks/")
- oauth_file = os.path.expanduser("~/.calcurse/caldav/oauth2_cred")
+ caldav_path = os.path.expanduser("~/.calcurse/caldav")
+ check_dir(caldav_path)
+
+ configfn = os.path.join(caldav_path, "config")
+ hookdir = os.path.join(caldav_path, "hooks")
+ oauth_file = os.path.join(caldav_path, "oauth2_cred")
+ lockfn = os.path.join(caldav_path, "lock")
+ syncdbfn = os.path.join(caldav_path, "sync.db")
else:
- calcurse_data = os.getenv("XDG_DATA_HOME", os.path.expanduser("~/.local/share")) + "/calcurse"
- calcurse_config = os.getenv("XDG_CONFIG_HOME", os.path.expanduser("~/.config")) + "/calcurse"
-
- configfn = os.path.expanduser(calcurse_config + "/caldav/config")
- lockfn = os.path.expanduser(calcurse_data + "/caldav/lock")
- syncdbfn = os.path.expanduser(calcurse_data + "/caldav/sync.db")
- hookdir = os.path.expanduser(calcurse_config + "/caldav/hooks/")
- oauth_file = os.path.expanduser(calcurse_config + "/caldav/oauth2_cred")
+ xdg_config_home = os.getenv("XDG_CONFIG_HOME", os.path.expanduser("~/.config"))
+ xdg_data_home = os.getenv("XDG_DATA_HOME", os.path.expanduser("~/.local/share"))
+ caldav_config = os.path.join(xdg_config_home, "calcurse", "caldav")
+ caldav_data = os.path.join(xdg_data_home, "calcurse", "caldav")
+ check_dir(caldav_config)
+ check_dir(caldav_data)
+
+ configfn = os.path.join(caldav_config, "config")
+ hookdir = os.path.join(caldav_config, "hooks")
+ oauth_file = os.path.join(caldav_config, "oauth2_cred")
+
+ lockfn = os.path.join(caldav_data, "lock")
+ syncdbfn = os.path.join(caldav_data, "sync.db")
# Parse command line arguments.
parser = argparse.ArgumentParser('calcurse-caldav')
diff --git a/doc/calcurse.1.txt b/doc/calcurse.1.txt
index d8275d6..43b2549 100644
--- a/doc/calcurse.1.txt
+++ b/doc/calcurse.1.txt
@@ -57,7 +57,7 @@ The first form shows how to invoke calcurse interactively; the remainder is
command line forms.
The second form shows queries (as opposed to interactive use). For
-convenience, common queries have abbriviated forms shown in the third line.
+convenience, common queries have abbreviated forms shown in the third line.
All queries may be combined with filter options as well as format options.
The fourth form shows operations on the calcurse data files, one for
@@ -91,7 +91,7 @@ and issue reminders; it stops automatically when the interactive mode is
reentered.
This man page mainly describes the command-line mode. The following two
-subsections contain some general desriptions of command line options and usage.
+subsections contain some general descriptions of command line options and usage.
Input and Output Date Format
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -206,7 +206,7 @@ displays those for yesterday and today. The first form is equivalent to *-Q
*-g*, *--gc*::
Run the garbage collector for note files. The garbage collector removes
files from the +notes+ directory (see <<_files,FILES>>) that are no longer
- linked to an item. Ususally done automatically by setting the configuration
+ linked to an item. Usually done automatically by setting the configuration
option +general.autogc+ in the 'General Options' submenu in interactive mode.
*-G*, *--grep*::
diff --git a/doc/manual.txt b/doc/manual.txt
index cb59e8d..9cf015a 100644
--- a/doc/manual.txt
+++ b/doc/manual.txt
@@ -143,7 +143,7 @@ Install process
First you need to gunzip and untar the source archive:
----
-$ tar zxvf calcurse-4.5.1.tar.gz
+$ tar zxvf calcurse-4.6.0.tar.gz
----
Once you meet the requirements and have extracted the archive, the install
diff --git a/doc/repeat.txt b/doc/repeat.txt
index 16a71da..7b8679b 100644
--- a/doc/repeat.txt
+++ b/doc/repeat.txt
@@ -4,32 +4,144 @@ Repeat
Repeat an event or an appointment.
You must first select the item to be repeated by moving inside the appointment
-panel. Then running the repeat command will lead you to a set of three
-questions, with which you will be able to specify the repetition
-characteristics:
-
- o type: you can choose between a daily, weekly, monthly or
- yearly repetition by pressing 'D', 'W', 'M' or 'Y'
- respectively.
-
- o frequency: this indicates how often the item shall be repeated.
- For example, if you want to remember an anniversary,
- choose a 'yearly' repetition with a frequency of '1',
- which means it must be repeated every year. Another
- example: if you go to the restaurant every two days,
- choose a 'daily' repetition with a frequency of '2'.
-
- o ending date: this specifies when to stop repeating the selected
- event or appointment. To indicate an endless
- repetition, enter '0' and the item will be repeated
- forever.
-
-Notes
------
-
-* Repeated items are marked with an '*' inside the appointment panel, to be
- easily recognizable from non-repeated ones.
-
-* The 'Repeat' and 'Delete' command can be mixed to create complicated
- configurations, as it is possible to delete only one occurrence of a repeated
- item.
+panel. Then invoke the repeat command, and you will be asked you to select a
+simple or advanced repetition. A simple repetition will lead you to a set of
+three questions with which you specify the basic repetition characteristics:
+
+ o type: choose between a daily, weekly, monthly or yearly base period
+
+ o frequency: choose the interval between base periods. '1' means every day
+ (week, month or year), '2' means every other day (week, ...).
+ For example, if you want to remember an anniversary, choose a
+ yearly type with a frequency of 1, which means it will be
+ repeated every year. Another example: if you go to a restaurant
+ every second day, choose a daily type with a frequency of 2.
+
+ o until date: specifies a day after which the repetitions do not occur. To
+ indicate an endless repetition, enter 0 (zero) or RETURN, and
+ the item will be repeated forever.
+
+For an advanced repetition you may, in addition to the basic characteristics,
+specify three lists of either days of the week, months of the year or days of
+the month. The three lists modify the simple repetition in some way by either
+limiting or expanding the basic pattern.
+
+ o Weekdays: abbriviated names of days of the week (as they appear above
+ the calendar). For monthly or yearly repetitions the name may
+ have a numerical prefix (1, 2, ... or -1, -2, ...) to specify
+ a particular weekday of the month or year, counted from either
+ the start or the end of the month or year.
+
+ o Months: the numerical name of a month (1, 2,..., 12).
+
+ o Monthdays: the numerical name of a day of the month (1, 2,..., 31) or the
+ opposites (-1, -2,..., -31) which count from the end of the
+ month.
+
+For each list you may enter one or several values separated by spaces. The
+prompt for the list gives a hint as to the format. If you enter '?' only, you
+get very terse, context dependent information as to the effect on the
+repetition. Note that both format and effect depend on the basic type. The
+combined effect on the basic type of the listed days and months is derived
+from the iCalendar specification (RFC5545).
+
+Briefly, a weekday or monthday limits the repetitions of type daily, but
+expands those of type weekly, monthly and yearly. For example, with 'Weekdays'
+set to 'Sat Sun' a daily type (with frequency one) is only repeated on
+Saturdays and Sundays (two instead of seven repetitions per week), while a
+weekly type is also repeated on the extra day (two instead of one repetition
+per week).
+
+Similarly, a month limits the repetitions of type daily, weekly and monthly,
+but expands those of type yearly. For example, with 'Months' set to '3 10', a
+weekly type is only repeated in March and October, while a yearly type is also
+repeated in the extra month (two instead of one yearly repetition).
+
+Mnemonic. If the list type (day or month) is shorter than the basic type (day,
+week, month, year), it expands the repetitions of the basic type, if not, it
+limits them.
+
+There are a some important exceptions, though, for 'Weekdays':
+
+ o For a monthly type, the expanded repetitions are special: a weekday with a
+ prefix expands to that particular weekday of the month ('3Mon' = third
+ Monday), while a weekday without prefix expands to all weekdays of the
+ month ('Wed' = all Wednesdays). Furthermore, repetitions are limited if
+ 'Monthdays' is also set (for example, if 'Weekdays' is set to 'Fri' with
+ 'Monthdays' set to '13', the monthly repetition occurs only on Friday 13th).
+
+ o For a yearly type, the expanded repetitions are special and depend also on
+ the setting of 'Months'. A weekday with a prefix expands to that particular
+ weekday of the year ('-1Sun' = last Sunday of the year), or, if 'Months' is
+ also set, to that weekday of the listed months. A weekday without prefix
+ expands to all weekdays ('Thu' = all Thurdays in either the year or listed
+ months). Furthermore, repetitions are limited if 'Monthdays' is also set
+ as for monthly type.
+
+When you are finished setting up the repeating item, you may test it
+interactively with the 'next' command, a subcommand of the generic command
+(default ': n'). Invoked with a repeating item selected in the appointments
+panel, it will go to the next repetition. By doing this repeatedly, you may
+step through the repetitions one by one.
+
+If you edit an item that is already repeating, you will be led through all six
+characteristics and can modify any of them.
+
+Here are some typical examples. It is assumed that you have invoked the repeat
+command on what will become the first repetition and have selected an advanced
+repetition, that your date input format is dd/mm/yyyy, and that your language
+is english.
+
+ o an event that occurs every Tuesday and Thursday forever
+ type: weekly
+ frequency: 1
+ until: 0
+ weekdays: Tue Thu
+ months: (empty)
+ monthdays: (not possible)
+
+ o an event that occurs on workdays except in July forever (holidays are not
+ taken into account)
+ type: daily
+ frequency: 1
+ until: 0
+ weekdays: Mon Tue Wed Thu Fri
+ months: 1 2 3 4 5 6 8 9 10 11 12
+ monthdays: (empty)
+
+ o an appointment that occurs on the first and last Monday of the month forever
+ type: monthly
+ frequency: 1
+ until: 0
+ weekdays: 1Mon -1Mon
+ months: (empty)
+ monthdays: (empty)
+
+ o an appointment that occurs on all Wednesdays in June and July until the
+ end of June 2022
+ type: monthly
+ frequency: 1
+ until: 30/6/2022
+ weekdays: Wed
+ months: 6 7
+ monthdays: (empty)
+
+ o an event that occurs when Daylight Saving Time begins in the EU (last
+ Sunday in March)
+ type: yearly
+ frequency: 1
+ until: 0
+ weekdays: -1Sun
+ months: 3
+ monthdays: (empty)
+
+ o an event that occurs on the penultimate day of February forever
+ type: monthly
+ frequency: 1
+ until: 0
+ weekdays: (empty)
+ months: 2
+ monthdays: -2
+
+For an example that is not possible to specify consider an event that occurs
+on the last workday of each month.
diff --git a/src/apoint.c b/src/apoint.c
index 77ff8a0..4cb77f6 100644
--- a/src/apoint.c
+++ b/src/apoint.c
@@ -195,7 +195,7 @@ void apoint_write(struct apoint *o, FILE * f)
mem_free(str);
}
-struct apoint *apoint_scan(FILE * f, struct tm start, struct tm end,
+char *apoint_scan(FILE * f, struct tm start, struct tm end,
char state, char *note, struct item_filter *filter)
{
char buf[BUFSIZ], *newline;
@@ -203,15 +203,15 @@ struct apoint *apoint_scan(FILE * f, struct tm start, struct tm end,
struct apoint *apt = NULL;
int cond;
- EXIT_IF(!check_date(start.tm_year, start.tm_mon, start.tm_mday) ||
- !check_date(end.tm_year, end.tm_mon, end.tm_mday) ||
- !check_time(start.tm_hour, start.tm_min) ||
- !check_time(end.tm_hour, end.tm_min),
- _("date error in appointment"));
+ if (!check_date(start.tm_year, start.tm_mon, start.tm_mday) ||
+ !check_date(end.tm_year, end.tm_mon, end.tm_mday) ||
+ !check_time(start.tm_hour, start.tm_min) ||
+ !check_time(end.tm_hour, end.tm_min))
+ return _("illegal date in appointment");
/* Read the appointment description */
if (!fgets(buf, sizeof buf, f))
- return NULL;
+ return _("error in appointment description");
newline = strchr(buf, '\n');
if (newline)
@@ -226,8 +226,8 @@ struct apoint *apoint_scan(FILE * f, struct tm start, struct tm end,
tstart = mktime(&start);
tend = mktime(&end);
- EXIT_IF(tstart == -1 || tend == -1 || tstart > tend,
- _("date error in appointment"));
+ if (tstart == -1 || tend == -1 || tstart > tend)
+ return _("date error in appointment");
/* Filter item. */
if (filter) {
@@ -255,8 +255,7 @@ struct apoint *apoint_scan(FILE * f, struct tm start, struct tm end,
}
if (!apt)
apt = apoint_new(buf, note, tstart, tend - tstart, state);
-
- return apt;
+ return NULL;
}
void apoint_delete(struct apoint *apt)
diff --git a/src/calcurse.c b/src/calcurse.c
index 1f0696d..fe8b574 100644
--- a/src/calcurse.c
+++ b/src/calcurse.c
@@ -49,11 +49,12 @@ int count, reg;
*/
static void do_storage(int day_changed)
{
+ int pre_sel;
/*
* Save the selected item before rebuilding the day vector -
- * unless already set.
+ * unless a preselection is already set.
*/
- if (!day_check_sel_data())
+ if (!(pre_sel = day_check_sel_data()))
day_set_sel_data(ui_day_get_sel());
if (!day_changed)
@@ -64,7 +65,7 @@ static void do_storage(int day_changed)
/* The APP listbox. */
ui_day_load_items();
- if (day_changed)
+ if (day_changed && !pre_sel)
ui_day_sel_reset();
else
ui_day_find_sel();
@@ -556,7 +557,7 @@ static inline void key_generic_cmd(void)
int valid = 0, force = 0, ret;
char *error_msg;
- status_mesg(_("Command: [ h(elp) | w(rite)(!) | q(uit)(!) | wq(!) ]"), "");
+ status_mesg(_("Command: [ h(elp) | w(rite)(!) | q(uit)(!) | wq(!) | n(ext) ]"), "");
if (getstring(win[STA].p, cmd, BUFSIZ, 0, 1) != GETSTRING_VALID)
goto cleanup;
cmd_name = strtok(cmd, " ");
@@ -608,6 +609,47 @@ static inline void key_generic_cmd(void)
valid = 1;
}
+ if (!strcmp(cmd_name, "next") || !strcmp(cmd_name, "n")) {
+ struct day_item *item;
+ time_t day, next;
+ struct recur_apoint *rapt;
+ struct recur_event *rev;
+ int more = 0;
+
+ if (wins_slctd() != APP) {
+ error_msg =
+ _("Select a repeating item in the appointments panel.");
+ warnbox(error_msg);
+ goto cleanup;
+ }
+ day = date2sec(*ui_calendar_get_slctd_day(), 0, 0);
+ item = ui_day_get_sel();
+ if (item->type == RECUR_EVNT) {
+ rev = item->item.rev;
+ more = recur_next_occurrence(rev->day, -1, rev->rpt, &rev->exc,
+ day, &next);
+ } else if (item->type == RECUR_APPT) {
+ rapt = item->item.rapt;
+ more = recur_next_occurrence(rapt->start, rapt->dur, rapt->rpt,
+ &rapt->exc, day, &next);
+ } else {
+ error_msg = _("Not a repeating item.");
+ warnbox(error_msg);
+ goto cleanup;
+ }
+ if (!more) {
+ error_msg = _("Last repetition.");
+ warnbox(error_msg);
+ goto cleanup;
+ }
+ item->start = next;
+ ui_calendar_set_slctd_day(sec2date(next));
+ day_set_sel_data(item);
+ do_storage(1);
+
+ valid = 1;
+ }
+
if (!valid) {
asprintf(&error_msg, _("No such command: %s"), cmd);
status_mesg(error_msg, "");
diff --git a/src/calcurse.h b/src/calcurse.h
index d65d088..0c959a9 100644
--- a/src/calcurse.h
+++ b/src/calcurse.h
@@ -148,6 +148,12 @@
/* Calendar window. */
#define CALHEIGHT 8
+/*
+ * Week day numbering (0, 1,..., 6) which depends on the first day of the week.
+ * The argument (d) is the "Sunday"-numbering of member tm_wday in struct tm.
+ */
+#define WDAY(d) \
+ (ui_calendar_week_begins_on_monday() ? ((d ? d : WEEKINDAYS) - 1) : d)
/* Key definitions. */
#define CTRLVAL 0x1F
@@ -379,40 +385,57 @@ struct excp {
};
enum recur_type {
- RECUR_NO,
RECUR_DAILY,
RECUR_WEEKLY,
RECUR_MONTHLY,
RECUR_YEARLY,
- RECUR_TYPES
+ NBRECUR
};
-/* To describe an item's repetition. */
+/*
+ * Recurrence rule according to RFC5545; used
+ * - in each recurrent appointment/event instance
+ * - in passing parameters as a single function argument
+ */
struct rpt {
- enum recur_type type; /* repetition type */
- int freq; /* repetition frequency */
- time_t until; /* ending date for repeated event */
+ enum recur_type type; /* FREQ */
+ int freq; /* INTERVAL */
+ time_t until; /* UNTIL */
+ llist_t bymonth; /* BYMONTH list */
+ llist_t bywday; /* BY(WEEK)DAY list */
+ llist_t bymonthday; /* BYMONTHDAY list */
+ llist_t exc; /* EXDATE's */
};
+/* Types of integers in rrule lists. */
+typedef enum {
+ BYMONTH,
+ BYDAY_W,
+ BYDAY_M,
+ BYDAY_Y,
+ BYMONTHDAY,
+ NOLL
+} int_list_t;
+
/* Recurrent appointment definition. */
struct recur_apoint {
- struct rpt *rpt; /* information about repetition */
- llist_t exc; /* days when the item should not be repeated */
- time_t start; /* beggining of the appointment */
- long dur; /* duration of the appointment */
- char state; /* 8 bits to store item state */
- char *mesg; /* appointment description */
- char *note; /* note attached to appointment */
+ struct rpt *rpt; /* recurrence rule */
+ llist_t exc; /* recurrence exceptions (NOT rpt->exc) */
+ time_t start; /* start time */
+ long dur; /* duration */
+ char state; /* item state */
+ char *mesg; /* description */
+ char *note; /* attached note */
};
-/* Reccurent event definition. */
+/* Recurrent event definition. */
struct recur_event {
- struct rpt *rpt; /* information about repetition */
- llist_t exc; /* days when the item should not be repeated */
+ struct rpt *rpt; /* recurrence rule */
+ llist_t exc; /* recurrence exceptions (NOT rpt->exc) */
int id; /* event type */
- time_t day; /* day at which event occurs */
- char *mesg; /* event description */
- char *note; /* note attached to event */
+ time_t day; /* day of the event */
+ char *mesg; /* description */
+ char *note; /* attached note */
};
/* Generic pointer data type for appointments and events. */
@@ -762,7 +785,7 @@ void apoint_sec2str(struct apoint *, time_t, char *, char *);
char *apoint_tostr(struct apoint *);
char *apoint_hash(struct apoint *);
void apoint_write(struct apoint *, FILE *);
-struct apoint *apoint_scan(FILE *, struct tm, struct tm, char, char *,
+char *apoint_scan(FILE *, struct tm, struct tm, char, char *,
struct item_filter *);
void apoint_delete(struct apoint *);
struct notify_app *apoint_check_next(struct notify_app *, time_t);
@@ -860,7 +883,7 @@ unsigned event_inday(struct event *, time_t *);
char *event_tostr(struct event *);
char *event_hash(struct event *);
void event_write(struct event *, FILE *);
-struct event *event_scan(FILE *, struct tm, int, char *, struct item_filter *);
+char *event_scan(FILE *, struct tm, int, char *, struct item_filter *);
void event_delete(struct event *);
void event_paste_item(struct event *, time_t);
int event_dummy(struct day_item *);
@@ -1029,7 +1052,11 @@ void pcal_export_data(FILE *);
/* recur.c */
extern llist_ts_t recur_alist_p;
extern llist_t recur_elist;
-int recur_update_exc(llist_t *, char *);
+void recur_free_int_list(llist_t *);
+void recur_int_list_dup(llist_t *, llist_t *);
+void recur_free_exc_list(llist_t *);
+void recur_exc_dup(llist_t *, llist_t *);
+int recur_str2exc(llist_t *, char *);
char *recur_exc2str(llist_t *);
struct recur_event *recur_event_dup(struct recur_event *);
struct recur_apoint *recur_apoint_dup(struct recur_apoint *);
@@ -1042,17 +1069,16 @@ void recur_event_llist_init(void);
void recur_apoint_llist_free(void);
void recur_event_llist_free(void);
struct recur_apoint *recur_apoint_new(char *, char *, time_t, long, char,
- int, int, time_t, llist_t *);
-struct recur_event *recur_event_new(char *, char *, time_t, int, int, int,
- time_t, llist_t *);
+ struct rpt *);
+struct recur_event *recur_event_new(char *, char *, time_t, int,
+ struct rpt *);
char recur_def2char(enum recur_type);
int recur_char2def(char);
-struct recur_apoint *recur_apoint_scan(FILE *, struct tm, struct tm,
- char, int, struct tm, char *,
- llist_t *, char, struct item_filter *);
-struct recur_event *recur_event_scan(FILE *, struct tm, int, char,
- int, struct tm, char *, llist_t *,
- struct item_filter *);
+char *recur_apoint_scan(FILE *, struct tm, struct tm, char,
+ char *, struct item_filter *,
+ struct rpt *);
+char *recur_event_scan(FILE *, struct tm, int, char *,
+ struct item_filter *, struct rpt *);
char *recur_apoint_tostr(struct recur_apoint *);
char *recur_apoint_hash(struct recur_apoint *);
void recur_apoint_write(struct recur_apoint *, FILE *);
@@ -1060,22 +1086,27 @@ char *recur_event_tostr(struct recur_event *);
char *recur_event_hash(struct recur_event *);
void recur_event_write(struct recur_event *, FILE *);
void recur_save_data(FILE *);
-unsigned recur_item_find_occurrence(time_t, long, llist_t *, int,
- int, time_t, time_t, time_t *);
+unsigned recur_item_find_occurrence(time_t, long, struct rpt *, llist_t *,
+ time_t, time_t *);
unsigned recur_apoint_find_occurrence(struct recur_apoint *, time_t, time_t *);
unsigned recur_event_find_occurrence(struct recur_event *, time_t, time_t *);
-unsigned recur_item_inday(time_t, long, llist_t *, int, int, time_t, time_t);
+unsigned recur_item_inday(time_t, long, struct rpt *, llist_t *, time_t);
unsigned recur_apoint_inday(struct recur_apoint *, time_t *);
unsigned recur_event_inday(struct recur_event *, time_t *);
void recur_event_add_exc(struct recur_event *, time_t);
void recur_apoint_add_exc(struct recur_apoint *, time_t);
void recur_event_erase(struct recur_event *);
void recur_apoint_erase(struct recur_apoint *);
+void recur_bymonth(llist_t *, FILE *);
+void recur_bywday(enum recur_type, llist_t *, FILE *);
+void recur_bymonthday(llist_t *, FILE *);
void recur_exc_scan(llist_t *, FILE *);
void recur_apoint_check_next(struct notify_app *, time_t, time_t);
void recur_apoint_switch_notify(struct recur_apoint *);
void recur_event_paste_item(struct recur_event *, time_t);
void recur_apoint_paste_item(struct recur_apoint *, time_t);
+int recur_next_occurrence(time_t, long, struct rpt *, llist_t *, time_t, time_t *);
+
/* sigs.c */
void sigs_init(void);
@@ -1235,6 +1266,9 @@ int hash_matches(const char *, const char *);
int show_dialogs(void);
long overflow_add(long, long, long *);
long overflow_mul(long, long, long *);
+time_t next_wday(time_t, int);
+int wday_per_year(int, int);
+int wday_per_month(int, int, int);
/* vars.c */
extern int col, row;
diff --git a/src/day.c b/src/day.c
index 29184d9..2a1e1a8 100644
--- a/src/day.c
+++ b/src/day.c
@@ -360,7 +360,7 @@ static int day_store_recur_events(time_t date)
p.rev = rev;
time_t occurrence;
if (recur_event_find_occurrence(rev, date, &occurrence)) {
- day_add_item(RECUR_EVNT, rev->day, occurrence, p);
+ day_add_item(RECUR_EVNT, occurrence, occurrence, p);
e_nb++;
}
}
diff --git a/src/event.c b/src/event.c
index 375dd66..e0da4c1 100644
--- a/src/event.c
+++ b/src/event.c
@@ -149,7 +149,7 @@ void event_write(struct event *o, FILE * f)
}
/* Load the events from file */
-struct event *event_scan(FILE * f, struct tm start, int id, char *note,
+char *event_scan(FILE * f, struct tm start, int id, char *note,
struct item_filter *filter)
{
char buf[BUFSIZ], *nl;
@@ -157,13 +157,13 @@ struct event *event_scan(FILE * f, struct tm start, int id, char *note,
struct event *ev = NULL;
int cond;
- EXIT_IF(!check_date(start.tm_year, start.tm_mon, start.tm_mday) ||
- !check_time(start.tm_hour, start.tm_min),
- _("date error in event"));
+ if (!check_date(start.tm_year, start.tm_mon, start.tm_mday) ||
+ !check_time(start.tm_hour, start.tm_min))
+ return _("illegal date in event");
/* Read the event description */
if (!fgets(buf, sizeof buf, f))
- return NULL;
+ return _("error in appointment description");
nl = strchr(buf, '\n');
if (nl) {
@@ -177,8 +177,9 @@ struct event *event_scan(FILE * f, struct tm start, int id, char *note,
start.tm_mon--;
tstart = mktime(&start);
- EXIT_IF(tstart == -1, _("date error in the event\n"));
- tend = tstart + DAYINSEC - 1;
+ if (tstart == -1)
+ return _("date error in event\n");
+ tend = ENDOFDAY(tstart);
/* Filter item. */
if (filter) {
@@ -205,8 +206,7 @@ struct event *event_scan(FILE * f, struct tm start, int id, char *note,
}
if (!ev)
ev = event_new(buf, note, tstart, id);
-
- return ev;
+ return NULL;
}
/* Delete an event from the list. */
diff --git a/src/ical.c b/src/ical.c
index f6b9bd9..5ab6846 100644
--- a/src/ical.c
+++ b/src/ical.c
@@ -54,6 +54,15 @@ typedef enum {
EVENT
} ical_vevent_e;
+typedef enum {
+ NO_PROPERTY,
+ SUMMARY,
+ DESCRIPTION,
+ LOCATION,
+ COMMENT,
+ STATUS
+} ical_property_e;
+
typedef struct {
enum recur_type type;
int freq;
@@ -69,8 +78,8 @@ static void ical_export_apoints(FILE *, int);
static void ical_export_todo(FILE *, int);
static void ical_export_footer(FILE *);
-static const char *ical_recur_type[RECUR_TYPES] =
- { "", "DAILY", "WEEKLY", "MONTHLY", "YEARLY" };
+static const char *ical_recur_type[NBRECUR] =
+ { "DAILY", "WEEKLY", "MONTHLY", "YEARLY" };
/* Escape characters in field before printing */
static void ical_format_line(FILE * stream, char * field, char * msg)
@@ -128,7 +137,7 @@ static void ical_export_recur_events(FILE * stream, int export_uid)
struct recur_event *rev = LLIST_GET_DATA(i);
date_sec2date_fmt(rev->day, ICALDATEFMT, ical_date);
fputs("BEGIN:VEVENT\n", stream);
- fprintf(stream, "DTSTART:%s\n", ical_date);
+ fprintf(stream, "DTSTART;VALUE=DATE:%s\n", ical_date);
fprintf(stream, "RRULE:FREQ=%s;INTERVAL=%d",
ical_recur_type[rev->rpt->type], rev->rpt->freq);
@@ -366,17 +375,24 @@ static void ical_store_todo(int priority, int completed, char *mesg,
static void
ical_store_event(char *mesg, char *note, long day, long end,
- ical_rpt_t * rpt, llist_t * exc, const char *fmt_ev,
+ ical_rpt_t *irpt, llist_t *exc, const char *fmt_ev,
const char *fmt_rev)
{
const int EVENTID = 1;
struct event *ev;
struct recur_event *rev;
- if (rpt) {
- rev = recur_event_new(mesg, note, day, EVENTID, rpt->type,
- rpt->freq, rpt->until, exc);
- mem_free(rpt);
+ if (irpt) {
+ struct rpt rpt;
+ rpt.type = irpt->type;
+ rpt.freq = irpt->freq;
+ rpt.until = irpt->until;
+ LLIST_INIT(&rpt.bymonth);
+ LLIST_INIT(&rpt.bywday);
+ LLIST_INIT(&rpt.bymonthday);
+ rpt.exc = *exc;
+ rev = recur_event_new(mesg, note, day, EVENTID, &rpt);
+ mem_free(irpt);
if (fmt_rev)
print_recur_event(fmt_rev, day, rev);
goto cleanup;
@@ -397,14 +413,15 @@ ical_store_event(char *mesg, char *note, long day, long end,
* event starts, so we need to do some conversion here.
*/
end = day + ((end - day - 1) / DAYINSEC) * DAYINSEC;
- rpt = mem_malloc(sizeof(ical_rpt_t));
- rpt->type = RECUR_DAILY;
- rpt->freq = 1;
- rpt->count = 0;
- rpt->until = end;
- rev = recur_event_new(mesg, note, day, EVENTID, rpt->type,
- rpt->freq, rpt->until, exc);
- mem_free(rpt);
+ struct rpt rpt;
+ rpt.type = RECUR_DAILY;
+ rpt.freq = 1;
+ rpt.until = end;
+ LLIST_INIT(&rpt.bymonth);
+ LLIST_INIT(&rpt.bywday);
+ LLIST_INIT(&rpt.bymonthday);
+ rpt.exc = *exc;
+ rev = recur_event_new(mesg, note, day, EVENTID, &rpt);
if (fmt_rev)
print_recur_event(fmt_rev, day, rev);
@@ -415,7 +432,7 @@ cleanup:
static void
ical_store_apoint(char *mesg, char *note, long start, long dur,
- ical_rpt_t * rpt, llist_t * exc, int has_alarm,
+ ical_rpt_t * irpt, llist_t * exc, int has_alarm,
const char *fmt_apt, const char *fmt_rapt)
{
char state = 0L;
@@ -424,10 +441,17 @@ ical_store_apoint(char *mesg, char *note, long start, long dur,
if (has_alarm)
state |= APOINT_NOTIFY;
- if (rpt) {
- rapt = recur_apoint_new(mesg, note, start, dur, state,
- rpt->type, rpt->freq, rpt->until, exc);
- mem_free(rpt);
+ if (irpt) {
+ struct rpt rpt;
+ rpt.type = irpt->type;
+ rpt.freq = irpt->freq;
+ rpt.until = irpt->until;
+ LLIST_INIT(&rpt.bymonth);
+ LLIST_INIT(&rpt.bywday);
+ LLIST_INIT(&rpt.bymonthday);
+ rpt.exc = *exc;
+ rapt = recur_apoint_new(mesg, note, start, dur, state, &rpt);
+ mem_free(irpt);
if (fmt_rapt)
print_recur_apoint(fmt_rapt, start, rapt->start, rapt);
} else {
@@ -440,14 +464,16 @@ ical_store_apoint(char *mesg, char *note, long start, long dur,
}
/*
- * Returns an allocated string representing the argument string with escaped
- * characters decoded, or NULL on error.
- * The string is assumed to be the value part of a SUMMARY or DESCRIPTION line.
+ * Return an allocated string containing the decoded 'line' or NULL on error.
+ * The last arguments are used to format a note file entry.
+ * The line is assumed to be the value part of a content line of type TEXT or
+ * INTEGER (RFC 5545, 3.3.11 and 3.3.8) without list or field separators (3.1.1).
*/
-static char *ical_unformat_line(char *line)
+static char *ical_unformat_line(char *line, int eol, int indentation)
{
struct string s;
char *p;
+ const char *INDENT = " ";
string_init(&s);
for (p = line; *p; p++) {
@@ -457,6 +483,8 @@ static char *ical_unformat_line(char *line)
case 'N':
case 'n':
string_catf(&s, "%c", '\n');
+ if (indentation)
+ string_catf(&s, "%s", INDENT);
p++;
break;
case '\\':
@@ -472,9 +500,7 @@ static char *ical_unformat_line(char *line)
break;
case ',':
case ';':
- /*
- * No list or field separator allowed.
- */
+ /* No list or field separator allowed. */
mem_free(s.buf);
return NULL;
default:
@@ -482,6 +508,9 @@ static char *ical_unformat_line(char *line)
break;
}
}
+ /* Add the final EOL removed by ical_readline(). */
+ if (eol)
+ string_catf(&s, "\n");
return string_buf(&s);
}
@@ -550,39 +579,57 @@ ical_chk_header(FILE * fd, char *buf, char *lstore, unsigned *lineno,
}
/*
+ * Return event type from a DTSTART/DTEND/EXDATE property.
+ */
+static ical_vevent_e ical_get_type(char *c_line)
+{
+ const char vparam[] = ";VALUE=DATE";
+ char *p;
+
+ if ((p = strstr(c_line, vparam))) {
+ p += sizeof(vparam) - 1;
+ if (*p == ':' || *p == ';')
+ return EVENT;
+ }
+
+ return APPOINTMENT;
+}
+
+/*
* iCalendar date-time format is based on the ISO 8601 complete
* representation. It should be something like : DATE 'T' TIME
* where DATE is 'YYYYMMDD' and TIME is 'HHMMSS'.
* The time and 'T' separator are optional (in the case of an day-long event).
*
- * Optionally, if the type pointer is given, specify if it is an event
- * (no time is given, meaning it is an all-day event), or an appointment
- * (time is given).
+ * The type argument is either APPOINTMENT or EVENT and the time format must
+ * agree.
*
* The timezone is not yet handled by calcurse.
*/
-static time_t ical_datetime2time_t(char *datestr, ical_vevent_e * type)
+static time_t ical_datetime2time_t(char *datestr, ical_vevent_e type)
{
- const int FORMAT_DATE = 3, FORMAT_DATETIME = 6, FORMAT_DATETIMEZ = 7;
+ const int INVALID = 0, DATE = 3, DATETIME = 6, DATETIMEZ = 7;
struct date date;
unsigned hour, min, sec;
char c;
int format;
+ EXIT_IF(type == UNDEFINED, "event type not set");
+
format = sscanf(datestr, "%04u%02u%02uT%02u%02u%02u%c",
&date.yyyy, &date.mm, &date.dd, &hour, &min, &sec, &c);
- if (format == FORMAT_DATE) {
- if (type)
- *type = EVENT;
+ if (format == DATE && strlen(datestr) > 8)
+ format = INVALID;
+ if (format == DATETIMEZ && c != 'Z')
+ format = DATETIME;
+
+ if (format == DATE && type == EVENT)
return date2sec(date, 0, 0);
- } else if (format == FORMAT_DATETIME || format == FORMAT_DATETIMEZ) {
- if (type)
- *type = APPOINTMENT;
- if (format == FORMAT_DATETIMEZ && c == 'Z')
- return utcdate2sec(date, hour, min);
- else
- return date2sec(date, hour, min);
- }
+ else if (format == DATETIME && type == APPOINTMENT)
+ return date2sec(date, hour, min);
+ else if (format == DATETIMEZ && type == APPOINTMENT)
+ return utcdate2sec(date, hour, min);
+
return 0;
}
@@ -616,15 +663,22 @@ static long ical_durtime2long(char *timestr)
}
/*
- * Extract from RFC2445:
+ * Extract from RFC2445 section 3.8.2.5:
+ *
+ * Property Name: DURATION
+ *
+ * Purpose: This property specifies a positive duration of time.
+ *
+ * Value Type: DURATION
+ *
+ * and section 3.3.6:
*
* Value Name: DURATION
*
* Purpose: This value type is used to identify properties that contain
- * duration of time.
+ * a duration of time.
*
- * Formal Definition: The value type is defined by the following
- * notation:
+ * Format Definition: The value type is defined by the following notation:
*
* dur-value = (["+"] / "-") "P" (dur-date / dur-time / dur-week)
* dur-date = dur-day [dur-time]
@@ -640,42 +694,36 @@ static long ical_durtime2long(char *timestr)
* A duration of 7 weeks would be:
* P7W
*/
-static long ical_dur2long(char *durstr)
+static long ical_dur2long(char *durstr, ical_vevent_e type)
{
- char *p;
+ char *p = durstr, c;
int bytes_read;
- struct {
- unsigned week, day;
- } date;
-
- memset(&date, 0, sizeof date);
-
- p = strchr(durstr, 'P');
- if (!p)
- return -1;
- p++;
+ unsigned week, day;
if (*p == '-')
- return -1;
+ return 0;
if (*p == '+')
p++;
+ if (*p != 'P')
+ return 0;
- if (*p == 'T') {
+ p++;
+ if (*p == 'T' && type == APPOINTMENT)
/* dur-time */
return ical_durtime2long(p);
- } else if (strchr(p, 'W')) {
+ else if (sscanf(p, "%u%c", &week, &c) == 2 && c == 'W')
/* dur-week */
- if (sscanf(p, "%u", &date.week) == 1)
- return date.week * WEEKINDAYS * DAYINSEC;
- } else if (strchr(p, 'D')) {
+ return week * WEEKINDAYS * DAYINSEC;
+ else if (sscanf(p, "%u%c%n", &day, &c, &bytes_read) == 2 && c == 'D') {
/* dur-date */
- if (sscanf(p, "%uD%n", &date.day, &bytes_read) == 1) {
- p += bytes_read;
- return date.day * DAYINSEC + ical_durtime2long(p);
- }
+ p += bytes_read;
+ if (*p == 'T' && type == APPOINTMENT)
+ return day * DAYINSEC + ical_durtime2long(p);
+ else if (*p != 'T' && type == EVENT)
+ return day * DAYINSEC;
}
- return -1;
+ return 0;
}
/*
@@ -713,8 +761,8 @@ static char *ical_get_value(char *p)
return NULL;
for (; *p != ':'; p++) {
if (*p == '"')
- for (p++; *p != '"' && *p != '\0'; p++);
- if (*p == '\0')
+ for (p++; *p && *p != '"'; p++);
+ if (!*p)
return NULL;
}
@@ -758,8 +806,10 @@ static char *ical_get_value(char *p)
* ( ";" x-name "=" text )
* )
*/
-static ical_rpt_t *ical_read_rrule(FILE * log, char *rrulestr,
- unsigned *noskipped, const int itemline)
+static ical_rpt_t *ical_read_rrule(FILE *log, char *rrulestr,
+ unsigned *noskipped,
+ const int itemline,
+ ical_vevent_e type)
{
const char count[] = "COUNT=";
const char interv[] = "INTERVAL=";
@@ -768,6 +818,12 @@ static ical_rpt_t *ical_read_rrule(FILE * log, char *rrulestr,
ical_rpt_t *rpt;
char *p;
+ /* See DTSTART. */
+ if (type == UNDEFINED) {
+ ical_log(log, ICAL_VEVENT, itemline,
+ _("need DTSTART to determine event type."));
+ return NULL;
+ }
p = ical_get_value(rrulestr);
if (!p) {
ical_log(log, ICAL_VEVENT, itemline,
@@ -813,7 +869,14 @@ static ical_rpt_t *ical_read_rrule(FILE * log, char *rrulestr,
* specified, counts as the first occurrence.
*/
if ((p = strstr(rrulestr, "UNTIL")) != NULL) {
- rpt->until = ical_datetime2time_t(strchr(p, '=') + 1, NULL);
+ rpt->until = ical_datetime2time_t(strchr(p, '=') + 1, type);
+ if (!(rpt->until)) {
+ ical_log(log, ICAL_VEVENT, itemline,
+ _("invalid until format."));
+ (*noskipped)++;
+ mem_free(rpt);
+ return NULL;
+ }
} else {
unsigned cnt;
char *countstr;
@@ -836,11 +899,8 @@ static ical_rpt_t *ical_read_rrule(FILE * log, char *rrulestr,
return rpt;
}
-static void ical_add_exc(llist_t * exc_head, long date)
+static void ical_add_exc(llist_t * exc_head, time_t date)
{
- if (date == 0)
- return;
-
struct excp *exc = mem_malloc(sizeof(struct excp));
exc->st = date;
@@ -848,15 +908,30 @@ static void ical_add_exc(llist_t * exc_head, long date)
}
/*
- * This property defines the list of date/time exceptions for a
+ * This property defines a comma-separated list of date/time exceptions for a
* recurring calendar component.
*/
static int
-ical_read_exdate(llist_t * exc, FILE * log, char *exstr,
- unsigned *noskipped, const int itemline)
+ical_read_exdate(llist_t * exc, FILE * log, char *exstr, unsigned *noskipped,
+ const int itemline, ical_vevent_e type)
{
char *p, *q;
+ time_t t;
+ int n;
+ /* See DTSTART. */
+ if (type == UNDEFINED) {
+ ical_log(log, ICAL_VEVENT, itemline,
+ _("need DTSTART to determine event type."));
+ (*noskipped)++;
+ return 0;
+ }
+ if (type != ical_get_type(exstr)) {
+ ical_log(log, ICAL_VEVENT, itemline,
+ _("invalid exception date value type."));
+ (*noskipped)++;
+ return 0;
+ }
p = ical_get_value(exstr);
if (!p) {
ical_log(log, ICAL_VEVENT, itemline,
@@ -865,50 +940,72 @@ ical_read_exdate(llist_t * exc, FILE * log, char *exstr,
return 0;
}
- while ((q = strchr(p, ',')) != NULL) {
- char buf[BUFSIZ];
- const int buflen = q - p;
-
- strncpy(buf, p, buflen);
- buf[buflen] = '\0';
- ical_add_exc(exc, ical_datetime2time_t(buf, NULL));
- p = ++q;
+ /* Count the exceptions and replace commas by zeroes */
+ for (q = p, n = 1; (q = strchr(q, ',')); *q = '\0', q++, n++)
+ ;
+ while (n) {
+ if (!(t = ical_datetime2time_t(p, type))) {
+ ical_log(log, ICAL_VEVENT, itemline,
+ _("invalid exception."));
+ (*noskipped)++;
+ return 0;
+ }
+ ical_add_exc(exc, t);
+ p = strchr(p, '\0') + 1;
+ n--;
}
- ical_add_exc(exc, ical_datetime2time_t(p, NULL));
return 1;
}
-/* Return an allocated string containing the name of the newly created note. */
-static char *ical_read_note(char *line, unsigned *noskipped,
+/*
+ * Return an allocated string containing a property value to be written in a
+ * note file or NULL on error.
+ */
+static char *ical_read_note(char *line, ical_property_e property, unsigned *noskipped,
ical_types_e item_type, const int itemline,
FILE * log)
{
- char *p, *notestr, *note;
+ const int EOL = 1,
+ INDENT = (property != DESCRIPTION);
+ char *p, *pname, *notestr;
+
+ switch (property) {
+ case DESCRIPTION:
+ pname = "description";
+ break;
+ case LOCATION:
+ pname = "location";
+ break;
+ case COMMENT:
+ pname = "comment";
+ break;
+ case STATUS:
+ pname = "status";
+ break;
+ default:
+ pname = "no property";
+ }
p = ical_get_value(line);
if (!p) {
- ical_log(log, item_type, itemline,
- _("malformed description line."));
+ asprintf(&p, _("malformed %s line."), pname);
+ ical_log(log, item_type, itemline, p);
+ mem_free(p);
(*noskipped)++;
- return NULL;
+ notestr = NULL;
+ goto leave;
}
- notestr = ical_unformat_line(p);
+ notestr = ical_unformat_line(p, EOL, INDENT);
if (!notestr) {
- ical_log(log, item_type, itemline, _("malformed description."));
- (*noskipped)++;
- return NULL;
- } else if (strlen(notestr) == 0) {
- mem_free(notestr);
- ical_log(log, item_type, itemline, _("empty description."));
+ asprintf(&p, _("malformed %s."), pname);
+ ical_log(log, item_type, itemline, p);
+ mem_free(p);
(*noskipped)++;
- return NULL;
- } else {
- note = generate_note(notestr);
- mem_free(notestr);
- return note;
}
+ leave:
+ return notestr;
}
/* Returns an allocated string containing the ical item summary. */
@@ -916,30 +1013,31 @@ static char *ical_read_summary(char *line, unsigned *noskipped,
ical_types_e item_type, const int itemline,
FILE * log)
{
- char *p, *summary;
+ const int EOL = 0, INDENT = 0;
+ char *p, *summary = NULL;
p = ical_get_value(line);
if (!p) {
- ical_log(log, item_type, itemline, _("malformed summary line"));
+ ical_log(log, item_type, itemline, _("malformed summary line."));
(*noskipped)++;
- return NULL;
+ goto leave;
}
- summary = ical_unformat_line(p);
+ summary = ical_unformat_line(p, EOL, INDENT);
if (!summary) {
ical_log(log, item_type, itemline, _("malformed summary."));
(*noskipped)++;
- return NULL;
+ goto leave;
}
- /* Event summaries must not contain newlines. */
+ /* An event summary is one line only. */
if (strchr(summary, '\n')) {
ical_log(log, item_type, itemline, _("line break in summary."));
(*noskipped)++;
mem_free(summary);
- return NULL;
+ summary = NULL;
}
-
+ leave:
return summary;
}
@@ -951,21 +1049,26 @@ ical_read_event(FILE * fdi, FILE * log, unsigned *noevents,
{
const int ITEMLINE = *lineno - !feof(fdi);
ical_vevent_e vevent_type;
- char *p;
+ ical_property_e property;
+ char *p, *note = NULL, *comment;
+ const char *SEPARATOR = "-- \n";
+ struct string s;
struct {
llist_t exc;
ical_rpt_t *rpt;
- char *mesg, *note;
+ char *mesg, *desc, *loc, *comm, *stat, *note;
long start, end, dur;
int has_alarm;
} vevent;
- int skip_alarm;
+ int skip_alarm, has_note, separator;
vevent_type = UNDEFINED;
memset(&vevent, 0, sizeof vevent);
LLIST_INIT(&vevent.exc);
- skip_alarm = 0;
+ skip_alarm = has_note = separator = 0;
while (ical_readline(fdi, buf, lstore, lineno)) {
+ note = NULL;
+ property = NO_PROPERTY;
if (skip_alarm) {
/*
* Need to skip VALARM properties because some keywords
@@ -975,7 +1078,6 @@ ical_read_event(FILE * fdi, FILE * log, unsigned *noevents,
skip_alarm = 0;
continue;
}
-
if (starts_with_ci(buf, "END:VEVENT")) {
if (!vevent.mesg) {
ical_log(log, ICAL_VEVENT, ITEMLINE,
@@ -987,7 +1089,6 @@ ical_read_event(FILE * fdi, FILE * log, unsigned *noevents,
_("item start date is not defined."));
goto skip;
}
-
if (vevent_type == APPOINTMENT && vevent.dur == 0) {
if (vevent.end != 0) {
vevent.dur = vevent.end - vevent.start;
@@ -999,13 +1100,38 @@ ical_read_event(FILE * fdi, FILE * log, unsigned *noevents,
goto skip;
}
}
-
if (vevent.rpt && vevent.rpt->count) {
vevent.rpt->until =
ical_compute_rpt_until(vevent.start,
vevent.rpt);
}
-
+ if (has_note) {
+ /* Construct string with note file contents. */
+ string_init(&s);
+ if (vevent.desc) {
+ string_catf(&s, "%s", vevent.desc);
+ mem_free(vevent.desc);
+ if (separator)
+ string_catf(&s, SEPARATOR);
+ }
+ if (vevent.loc) {
+ string_catf(&s, _("Location: %s"),
+ vevent.loc);
+ mem_free(vevent.loc);
+ }
+ if (vevent.comm) {
+ string_catf(&s, _("Comment: %s"),
+ vevent.comm);
+ mem_free(vevent.comm);
+ }
+ if (vevent.stat) {
+ string_catf(&s, _("Status: %s"),
+ vevent.stat);
+ mem_free(vevent.stat);
+ }
+ vevent.note = generate_note(string_buf(&s));
+ mem_free(s.buf);
+ }
switch (vevent_type) {
case APPOINTMENT:
ical_store_apoint(vevent.mesg, vevent.note,
@@ -1028,11 +1154,19 @@ ical_read_event(FILE * fdi, FILE * log, unsigned *noevents,
goto skip;
break;
}
-
return;
}
-
if (starts_with_ci(buf, "DTSTART")) {
+ /*
+ * DTSTART has a value type: either DATE-TIME (by
+ * default) or DATE. Properties DTEND, DURATION and
+ * EXDATE and rrule part UNTIL must agree.
+ * Assume that DTSTART comes before the others even
+ * though RFC 5545 allows any order.
+ * In calcurse DATE-TIME implies an appointment, DATE an
+ * event.
+ */
+ vevent_type = ical_get_type(buf);
p = ical_get_value(buf);
if (!p) {
ical_log(log, ICAL_VEVENT, ITEMLINE,
@@ -1040,13 +1174,26 @@ ical_read_event(FILE * fdi, FILE * log, unsigned *noevents,
goto skip;
}
- vevent.start = ical_datetime2time_t(p, &vevent_type);
+ vevent.start = ical_datetime2time_t(p, vevent_type);
if (!vevent.start) {
ical_log(log, ICAL_VEVENT, ITEMLINE,
- _("could not retrieve event start time."));
+ _("invalid or malformed event "
+ "start time."));
goto skip;
}
} else if (starts_with_ci(buf, "DTEND")) {
+ /* See DTSTART. */
+ if (vevent_type == UNDEFINED) {
+ ical_log(log, ICAL_VEVENT, ITEMLINE,
+ _("need DTSTART to determine "
+ "event type."));
+ goto skip;
+ }
+ if (vevent_type != ical_get_type(buf)) {
+ ical_log(log, ICAL_VEVENT, ITEMLINE,
+ _("invalid end time value type."));
+ goto skip;
+ }
p = ical_get_value(buf);
if (!p) {
ical_log(log, ICAL_VEVENT, ITEMLINE,
@@ -1054,27 +1201,40 @@ ical_read_event(FILE * fdi, FILE * log, unsigned *noevents,
goto skip;
}
- vevent.end = ical_datetime2time_t(p, &vevent_type);
+ vevent.end = ical_datetime2time_t(p, vevent_type);
if (!vevent.end) {
ical_log(log, ICAL_VEVENT, ITEMLINE,
- _("could not retrieve event end time."));
+ _("malformed event end time."));
goto skip;
}
} else if (starts_with_ci(buf, "DURATION")) {
- vevent.dur = ical_dur2long(buf);
- if (vevent.dur <= 0) {
+ /* See DTSTART. */
+ if (vevent_type == UNDEFINED) {
+ ical_log(log, ICAL_VEVENT, ITEMLINE,
+ _("need DTSTART to determine "
+ "event type."));
+ goto skip;
+ }
+ p = ical_get_value(buf);
+ if (!p) {
ical_log(log, ICAL_VEVENT, ITEMLINE,
- _("item duration malformed."));
+ _("malformed duration line."));
+ goto skip;
+ }
+ vevent.dur = ical_dur2long(p, vevent_type);
+ if (!vevent.dur) {
+ ical_log(log, ICAL_VEVENT, ITEMLINE,
+ _("invalid duration."));
goto skip;
}
} else if (starts_with_ci(buf, "RRULE")) {
vevent.rpt = ical_read_rrule(log, buf, noskipped,
- ITEMLINE);
+ ITEMLINE, vevent_type);
if (!vevent.rpt)
goto cleanup;
} else if (starts_with_ci(buf, "EXDATE")) {
if (!ical_read_exdate(&vevent.exc, log, buf, noskipped,
- ITEMLINE))
+ ITEMLINE, vevent_type))
goto cleanup;
} else if (starts_with_ci(buf, "SUMMARY")) {
vevent.mesg = ical_read_summary(buf, noskipped,
@@ -1084,23 +1244,84 @@ ical_read_event(FILE * fdi, FILE * log, unsigned *noevents,
} else if (starts_with_ci(buf, "BEGIN:VALARM")) {
skip_alarm = vevent.has_alarm = 1;
} else if (starts_with_ci(buf, "DESCRIPTION")) {
- vevent.note = ical_read_note(buf, noskipped,
- ICAL_VEVENT, ITEMLINE, log);
- if (!vevent.note)
+ property = DESCRIPTION;
+ } else if (starts_with_ci(buf, "LOCATION")) {
+ property = LOCATION;
+ } else if (starts_with_ci(buf, "COMMENT")) {
+ property = COMMENT;
+ } else if (starts_with_ci(buf, "STATUS")) {
+ property = STATUS;
+ }
+ if (property) {
+ note = ical_read_note(buf, property, noskipped,
+ ICAL_VEVENT, ITEMLINE, log);
+ if (!note)
goto cleanup;
+ separator = (property != DESCRIPTION);
+ has_note = 1;
+ }
+ switch (property) {
+ case DESCRIPTION:
+ if (vevent.desc) {
+ ical_log(log, ICAL_VEVENT, ITEMLINE,
+ _("only one description allowed."));
+ goto skip;
+ }
+ vevent.desc = note;
+ break;
+ case LOCATION:
+ if (vevent.loc) {
+ ical_log(log, ICAL_VEVENT, ITEMLINE,
+ _("only one location allowed."));
+ goto skip;
+ }
+ vevent.loc = note;
+ break;
+ case COMMENT:
+ /* There may be more than one. */
+ if (vevent.comm) {
+ asprintf(&comment, "%sComment: %s",
+ vevent.comm, note);
+ mem_free(vevent.comm);
+ vevent.comm = comment;
+ } else
+ vevent.comm = note;
+ break;
+ case STATUS:
+ if (vevent.stat) {
+ ical_log(log, ICAL_VEVENT, ITEMLINE,
+ _("only one status allowed."));
+ goto skip;
+ }
+ if (!(starts_with(note, "TENTATIVE") ||
+ starts_with(note, "CONFIRMED") ||
+ starts_with(note, "CANCELLED"))) {
+ ical_log(log, ICAL_VEVENT, ITEMLINE,
+ _("invalid status value."));
+ goto skip;
+ }
+ vevent.stat = note;
+ break;
+ default:
+ break;
}
}
-
ical_log(log, ICAL_VEVENT, ITEMLINE,
_("The ical file seems to be malformed. "
"The end of item was not found."));
-
-skip:
+ skip:
(*noskipped)++;
-
cleanup:
- if (vevent.note)
- mem_free(vevent.note);
+ if (note)
+ mem_free(note);
+ if (vevent.desc)
+ mem_free(vevent.desc);
+ if (vevent.loc)
+ mem_free(vevent.loc);
+ if (vevent.comm)
+ mem_free(vevent.comm);
+ if (vevent.stat)
+ mem_free(vevent.stat);
if (vevent.mesg)
mem_free(vevent.mesg);
if (vevent.rpt)
@@ -1113,16 +1334,22 @@ ical_read_todo(FILE * fdi, FILE * log, unsigned *notodos, unsigned *noskipped,
char *buf, char *lstore, unsigned *lineno, const char *fmt_todo)
{
const int ITEMLINE = *lineno - !feof(fdi);
+ ical_property_e property;
+ char *note = NULL, *comment;
+ const char *SEPARATOR = "-- \n";
+ struct string s;
struct {
- char *mesg, *note;
+ char *mesg, *desc, *loc, *comm, *stat, *note;
int priority;
int completed;
} vtodo;
- int skip_alarm;
+ int skip_alarm, has_note, separator;
memset(&vtodo, 0, sizeof vtodo);
- skip_alarm = 0;
+ skip_alarm = has_note = separator = 0;
while (ical_readline(fdi, buf, lstore, lineno)) {
+ note = NULL;
+ property = NO_PROPERTY;
if (skip_alarm) {
/*
* Need to skip VALARM properties because some keywords
@@ -1132,20 +1359,44 @@ ical_read_todo(FILE * fdi, FILE * log, unsigned *notodos, unsigned *noskipped,
skip_alarm = 0;
continue;
}
-
if (starts_with_ci(buf, "END:VTODO")) {
if (!vtodo.mesg) {
ical_log(log, ICAL_VTODO, ITEMLINE,
_("could not retrieve item summary."));
goto cleanup;
}
-
+ if (has_note) {
+ /* Construct string with note file contents. */
+ string_init(&s);
+ if (vtodo.desc) {
+ string_catf(&s, "%s", vtodo.desc);
+ mem_free(vtodo.desc);
+ if (separator)
+ string_catf(&s, SEPARATOR);
+ }
+ if (vtodo.loc) {
+ string_catf(&s, _("Location: %s"),
+ vtodo.loc);
+ mem_free(vtodo.loc);
+ }
+ if (vtodo.comm) {
+ string_catf(&s, _("Comment: %s"),
+ vtodo.comm);
+ mem_free(vtodo.comm);
+ }
+ if (vtodo.stat) {
+ string_catf(&s, _("Status: %s"),
+ vtodo.stat);
+ mem_free(vtodo.stat);
+ }
+ vtodo.note = generate_note(string_buf(&s));
+ mem_free(s.buf);
+ }
ical_store_todo(vtodo.priority, vtodo.completed,
vtodo.mesg, vtodo.note, fmt_todo);
(*notodos)++;
return;
}
-
if (starts_with_ci(buf, "PRIORITY:")) {
sscanf(buf, "PRIORITY:%d\n", &vtodo.priority);
if (vtodo.priority < 0 || vtodo.priority > 9) {
@@ -1156,6 +1407,7 @@ ical_read_todo(FILE * fdi, FILE * log, unsigned *notodos, unsigned *noskipped,
}
} else if (starts_with_ci(buf, "STATUS:COMPLETED")) {
vtodo.completed = 1;
+ property = STATUS;
} else if (starts_with_ci(buf, "SUMMARY")) {
vtodo.mesg =
ical_read_summary(buf, noskipped, ICAL_VTODO,
@@ -1165,22 +1417,85 @@ ical_read_todo(FILE * fdi, FILE * log, unsigned *notodos, unsigned *noskipped,
} else if (starts_with_ci(buf, "BEGIN:VALARM")) {
skip_alarm = 1;
} else if (starts_with_ci(buf, "DESCRIPTION")) {
- vtodo.note = ical_read_note(buf, noskipped, ICAL_VTODO,
- ITEMLINE, log);
- if (!vtodo.note)
+ property = DESCRIPTION;
+ } else if (starts_with_ci(buf, "LOCATION")) {
+ property = LOCATION;
+ } else if (starts_with_ci(buf, "COMMENT")) {
+ property = COMMENT;
+ } else if (starts_with_ci(buf, "STATUS")) {
+ property = STATUS;
+ }
+ if (property) {
+ note = ical_read_note(buf, property, noskipped,
+ ICAL_VTODO, ITEMLINE, log);
+ if (!note)
goto cleanup;
+ separator = (property != DESCRIPTION);
+ has_note = 1;
+ }
+ switch (property) {
+ case DESCRIPTION:
+ if (vtodo.desc) {
+ ical_log(log, ICAL_VTODO, ITEMLINE,
+ _("only one description allowed."));
+ goto skip;
+ }
+ vtodo.desc = note;
+ break;
+ case LOCATION:
+ if (vtodo.loc) {
+ ical_log(log, ICAL_VTODO, ITEMLINE,
+ _("only one location allowed."));
+ goto skip;
+ }
+ vtodo.loc = note;
+ break;
+ case COMMENT:
+ /* There may be more than one. */
+ if (vtodo.comm) {
+ asprintf(&comment, "%sComment: %s",
+ vtodo.comm, note);
+ mem_free(vtodo.comm);
+ vtodo.comm = comment;
+ } else
+ vtodo.comm = note;
+ break;
+ case STATUS:
+ if (vtodo.stat) {
+ ical_log(log, ICAL_VTODO, ITEMLINE,
+ _("only one status allowed."));
+ goto skip;
+ }
+ if (!(starts_with(note, "NEEDS-ACTION") ||
+ starts_with(note, "COMPLETED") ||
+ starts_with(note, "IN-PROCESS") ||
+ starts_with(note, "CANCELLED"))) {
+ ical_log(log, ICAL_VTODO, ITEMLINE,
+ _("invalid status value."));
+ goto skip;
+ }
+ vtodo.stat = note;
+ break;
+ default:
+ break;
}
}
-
ical_log(log, ICAL_VTODO, ITEMLINE,
_("The ical file seems to be malformed. "
"The end of item was not found."));
-
-skip:
+ skip:
(*noskipped)++;
cleanup:
- if (vtodo.note)
- mem_free(vtodo.note);
+ if (note)
+ mem_free(note);
+ if (vtodo.desc)
+ mem_free(vtodo.desc);
+ if (vtodo.loc)
+ mem_free(vtodo.loc);
+ if (vtodo.comm)
+ mem_free(vtodo.comm);
+ if (vtodo.stat)
+ mem_free(vtodo.stat);
if (vtodo.mesg)
mem_free(vtodo.mesg);
}
diff --git a/src/io.c b/src/io.c
index 1782105..1caa6d3 100644
--- a/src/io.c
+++ b/src/io.c
@@ -553,13 +553,13 @@ void io_load_app(struct item_filter *filter)
FILE *data_file;
int c, is_appointment, is_event, is_recursive;
struct tm start, end, until, lt;
- llist_t exc;
+ struct rpt rpt;
time_t t;
int id = 0;
- int freq;
char type, state = 0L;
char note[MAX_NOTESIZ + 1], *notep;
unsigned line = 0;
+ char *scan_error;
t = time(NULL);
localtime_r(&t, &lt);
@@ -572,9 +572,10 @@ void io_load_app(struct item_filter *filter)
rewind(data_file);
for (;;) {
- LLIST_INIT(&exc);
is_appointment = is_event = is_recursive = 0;
line++;
+ scan_error = NULL;
+
c = getc(data_file);
if (c == EOF)
break;
@@ -630,102 +631,113 @@ void io_load_app(struct item_filter *filter)
if (c == '{') {
is_recursive = 1;
- if (fscanf(data_file, " %d%c ", &freq, &type) != 2)
+ if (fscanf(data_file, " %d%c ", &rpt.freq, &type) != 2)
io_load_error(path_apts, line,
_("syntax error in item repetition"));
-
+ else
+ rpt.type = recur_char2def(type);
c = getc(data_file);
- if (c == '}') { /* endless recurrent item */
- until.tm_year = 0;
- while ((c = getc(data_file)) == ' ') ;
- ungetc(c, data_file);
- } else if (c == '-' && getc(data_file) == '>') {
+ /* Optional until date */
+ if (c == '-' && getc(data_file) == '>') {
if (fscanf
(data_file, " %d / %d / %d ",
&until.tm_mon, &until.tm_mday,
&until.tm_year) != 3)
io_load_error(path_apts, line,
- _("syntax error in item repetition"));
+ _("syntax error in until date"));
+ if (!check_date(until.tm_year, until.tm_mon,
+ until.tm_mday))
+ io_load_error(path_apts, line,
+ _("until date error"));
+ until.tm_hour = 0;
+ until.tm_min = 0;
+ until.tm_sec = 0;
+ until.tm_isdst = -1;
+ until.tm_year -= 1900;
+ until.tm_mon--;
+ rpt.until = mktime(&until);
c = getc(data_file);
- if (c == '!') {
- ungetc(c, data_file);
- recur_exc_scan(&exc, data_file);
- while ((c =
- getc(data_file)) == ' ') ;
- ungetc(c, data_file);
- } else if (c == '}') {
- while ((c =
- getc(data_file)) == ' ') ;
- ungetc(c, data_file);
- } else {
+ } else
+ rpt.until = 0;
+ /* Optional bymonthday list */
+ if (c == 'd') {
+ if (rpt.type == RECUR_WEEKLY)
io_load_error(path_apts, line,
- _("syntax error in item repetition"));
- }
- } else if (c == '!') { /* endless item with exceptions */
+ _("BYMONTHDAY illegal with WEEKLY"));
ungetc(c, data_file);
- recur_exc_scan(&exc, data_file);
- while ((c = getc(data_file)) == ' ') ;
+ recur_bymonthday(&rpt.bymonthday, data_file);
+ c = getc(data_file);
+ } else
+ LLIST_INIT(&rpt.bymonthday);
+ /* Optional bywday list */
+ if (c == 'w') {
ungetc(c, data_file);
- until.tm_year = 0;
- } else {
+ recur_bywday(rpt.type, &rpt.bywday, data_file);
+ c = getc(data_file);
+ } else
+ LLIST_INIT(&rpt.bywday);
+ /* Optional bymonth list */
+ if (c == 'm') {
+ ungetc(c, data_file);
+ recur_bymonth(&rpt.bymonth, data_file);
+ c = getc(data_file);
+ } else
+ LLIST_INIT(&rpt.bymonth);
+ /* Optional exception dates */
+ if (c == '!') {
+ ungetc(c, data_file);
+ recur_exc_scan(&rpt.exc, data_file);
+ c = getc(data_file);
+ } else
+ LLIST_INIT(&rpt.exc);
+ /* End of recurrence rule */
+ if (c != '}')
io_load_error(path_apts, line,
- _("wrong format in the appointment or event"));
- /* NOTREACHED */
- }
- } else {
- ungetc(c, data_file);
+ _("missing end of recurrence"));
+ while ((c = getc(data_file)) == ' ') ;
}
/* Check if a note is attached to the item. */
- c = getc(data_file);
if (c == '>') {
note_read(note, data_file);
+ c = getc(data_file);
notep = note;
- } else {
+ } else
notep = NULL;
- ungetc(c, data_file);
- }
/*
* Last: read the item description and load it into its
* corresponding linked list, depending on the item type.
*/
if (is_appointment) {
- c = getc(data_file);
- if (c == '!') {
+ if (c == '!')
state |= APOINT_NOTIFY;
- while ((c = getc(data_file)) == ' ') ;
- ungetc(c, data_file);
- } else if (c == '|') {
+ else if (c == '|')
state = 0L;
- while ((c = getc(data_file)) == ' ') ;
- ungetc(c, data_file);
- } else {
+ else
io_load_error(path_apts, line,
- _("syntax error in item repetition"));
- }
- if (is_recursive) {
- recur_apoint_scan(data_file, start, end,
- type, freq, until, notep,
- &exc, state, filter);
- } else {
- apoint_scan(data_file, start, end, state,
+ _("syntax error in item state"));
+
+ if (is_recursive)
+ scan_error = recur_apoint_scan(data_file, start, end, state,
+ notep, filter, &rpt);
+ else
+ scan_error = apoint_scan(data_file, start, end, state,
notep, filter);
- }
} else if (is_event) {
- if (is_recursive) {
- recur_event_scan(data_file, start, id,
- type, freq, until, notep,
- &exc, filter);
- } else {
- event_scan(data_file, start, id, notep,
- filter);
- }
+ ungetc(c, data_file);
+ if (is_recursive)
+ scan_error = recur_event_scan(data_file, start, id, notep,
+ filter, &rpt);
+ else
+ scan_error = event_scan(data_file, start, id, notep, filter);
} else {
io_load_error(path_apts, line,
_("wrong format in the appointment or event"));
/* NOTREACHED */
}
+ if (scan_error)
+ io_load_error(path_apts, line, scan_error);
}
file_close(data_file, __FILE_POS__);
}
diff --git a/src/note.c b/src/note.c
index 2160874..92c1ecf 100644
--- a/src/note.c
+++ b/src/note.c
@@ -59,13 +59,9 @@ HTABLE_PROTOTYPE(htp, note_gc_hash)
char *generate_note(const char *str)
{
char *sha1 = mem_malloc(SHA1_DIGESTLEN * 2 + 1);
- char *notepath, *s;
+ char *notepath;
FILE *fp;
- /* Temporary hack */
- asprintf(&s, "%s\n", str);
- str = s;
-
sha1_digest(str, sha1);
asprintf(&notepath, "%s%s", path_notes, sha1);
fp = fopen(notepath, "w");
@@ -74,7 +70,6 @@ char *generate_note(const char *str)
fputs(str, fp);
file_close(fp, __FILE_POS__);
- mem_free(s);
mem_free(notepath);
return sha1;
}
diff --git a/src/notify.c b/src/notify.c
index 3d19511..a24beb2 100644
--- a/src/notify.c
+++ b/src/notify.c
@@ -505,8 +505,7 @@ void notify_check_repeated(struct recur_apoint *i)
current_time = time(NULL);
pthread_mutex_lock(&notify_app.mutex);
if (recur_item_find_occurrence
- (i->start, i->dur, &i->exc, i->rpt->type, i->rpt->freq,
- i->rpt->until, get_today(), &real_app_time)) {
+ (i->start, i->dur, i->rpt, &i->exc, get_today(), &real_app_time)) {
if (!notify_app.got_app) {
if (real_app_time - current_time <= DAYINSEC)
update_notify = 1;
@@ -547,12 +546,10 @@ int notify_same_recur_item(struct recur_apoint *i)
time_t item_start;
/* Tomorrow? */
- recur_item_find_occurrence(i->start, i->dur, &i->exc, i->rpt->type,
- i->rpt->freq, i->rpt->until,
+ recur_item_find_occurrence(i->start, i->dur, i->rpt, &i->exc,
NEXTDAY(get_today()), &item_start);
/* Today? */
- recur_item_find_occurrence(i->start, i->dur, &i->exc, i->rpt->type,
- i->rpt->freq, i->rpt->until,
+ recur_item_find_occurrence(i->start, i->dur, i->rpt, &i->exc,
get_today(), &item_start);
pthread_mutex_lock(&notify_app.mutex);
if (notify_app.got_app && item_start == notify_app.time)
diff --git a/src/pcal.c b/src/pcal.c
index 36fdd8e..78da0bb 100644
--- a/src/pcal.c
+++ b/src/pcal.c
@@ -56,24 +56,22 @@ typedef void (*cb_dump_t) (FILE *, long, long, char *);
*/
static void
foreach_date_dump(const long date_end, struct rpt *rpt, llist_t * exc,
- long item_first_date, long item_dur, char *item_mesg,
+ long item_start, long item_dur, char *item_mesg,
cb_dump_t cb_dump, FILE * stream)
{
long date, item_time;
struct tm lt;
time_t t;
- t = item_first_date;
+ t = item_start;
localtime_r(&t, &lt);
lt.tm_hour = lt.tm_min = lt.tm_sec = 0;
lt.tm_isdst = -1;
date = mktime(&lt);
- item_time = item_first_date - date;
+ item_time = item_start - date;
while (date <= date_end && date <= rpt->until) {
- if (recur_item_inday
- (item_first_date, item_dur, exc, rpt->type, rpt->freq,
- rpt->until, date)) {
+ if (recur_item_inday(item_start, item_dur, rpt, exc, date)) {
(*cb_dump) (stream, date + item_time, item_dur,
item_mesg);
}
diff --git a/src/recur.c b/src/recur.c
index 54c43ba..647ba11 100644
--- a/src/recur.c
+++ b/src/recur.c
@@ -46,12 +46,45 @@
llist_ts_t recur_alist_p;
llist_t recur_elist;
+static void free_int(int *i)
+{
+ mem_free(i);
+}
+
+void recur_free_int_list(llist_t *ilist)
+{
+ LLIST_FREE_INNER(ilist, free_int);
+ LLIST_FREE(ilist);
+}
+
+void recur_int_list_dup(llist_t *l, llist_t *ilist)
+{
+ llist_item_t *i;
+ int *o, *p;
+
+ LLIST_INIT(l);
+
+ if (ilist->head) {
+ LLIST_FOREACH(ilist, i) {
+ p = LLIST_GET_DATA(i);
+ o = mem_malloc(sizeof(int));
+ *o = *p;
+ LLIST_ADD(l, o);
+ }
+ }
+}
+
+static int int_cmp(int *list, int *i)
+{
+ return *list == *i;
+}
+
static void free_exc(struct excp *exc)
{
mem_free(exc);
}
-static void free_exc_list(llist_t * exc)
+void recur_free_exc_list(llist_t * exc)
{
LLIST_FREE_INNER(exc, free_exc);
LLIST_FREE(exc);
@@ -62,6 +95,11 @@ static int exc_cmp_day(struct excp *a, struct excp *b)
return a->st < b->st ? -1 : (a->st == b->st ? 0 : 1);
}
+static int exc_inday(struct excp *exc, time_t *day_start)
+{
+ return (date_cmp_day(exc->st, *day_start) == 0);
+}
+
static void recur_add_exc(llist_t * exc, time_t day)
{
struct excp *o = mem_malloc(sizeof(struct excp));
@@ -70,7 +108,7 @@ static void recur_add_exc(llist_t * exc, time_t day)
LLIST_ADD_SORTED(exc, o, exc_cmp_day);
}
-static void exc_dup(llist_t * in, llist_t * exc)
+void recur_exc_dup(llist_t * in, llist_t * exc)
{
llist_item_t *i;
@@ -103,10 +141,10 @@ char *recur_exc2str(llist_t *exc)
}
/*
- * Update the list of exceptions from a string of days. Any positive number of
+ * Update a list of exceptions from a string of days. Any positive number of
* spaces are allowed before, between and after the days.
*/
-int recur_update_exc(llist_t *exc, char *days)
+int recur_str2exc(llist_t *exc, char *days)
{
int updated = 0;
char *d;
@@ -130,11 +168,11 @@ int recur_update_exc(llist_t *exc, char *days)
else
break;
}
- free_exc_list(exc);
- exc_dup(exc, &nexc);
+ recur_free_exc_list(exc);
+ recur_exc_dup(exc, &nexc);
updated = 1;
cleanup:
- free_exc_list(&nexc);
+ recur_free_exc_list(&nexc);
return updated;
}
@@ -149,11 +187,16 @@ struct recur_event *recur_event_dup(struct recur_event *in)
rev->mesg = mem_strdup(in->mesg);
rev->rpt = mem_malloc(sizeof(struct rpt));
+ /* Note. The linked lists are NOT copied and no memory allocated. */
rev->rpt->type = in->rpt->type;
rev->rpt->freq = in->rpt->freq;
rev->rpt->until = in->rpt->until;
+ LLIST_INIT(&rev->rpt->bymonth);
+ LLIST_INIT(&rev->rpt->bywday);
+ LLIST_INIT(&rev->rpt->bymonthday);
+ LLIST_INIT(&rev->rpt->exc);
- exc_dup(&rev->exc, &in->exc);
+ recur_exc_dup(&rev->exc, &in->exc);
if (in->note)
rev->note = mem_strdup(in->note);
@@ -176,11 +219,16 @@ struct recur_apoint *recur_apoint_dup(struct recur_apoint *in)
rapt->mesg = mem_strdup(in->mesg);
rapt->rpt = mem_malloc(sizeof(struct rpt));
+ /* Note. The linked lists are NOT copied and no memory allocated. */
rapt->rpt->type = in->rpt->type;
rapt->rpt->freq = in->rpt->freq;
rapt->rpt->until = in->rpt->until;
+ LLIST_INIT(&rapt->rpt->bymonth);
+ LLIST_INIT(&rapt->rpt->bywday);
+ LLIST_INIT(&rapt->rpt->bymonthday);
+ LLIST_INIT(&rapt->rpt->exc);
- exc_dup(&rapt->exc, &in->exc);
+ recur_exc_dup(&rapt->exc, &in->exc);
if (in->note)
rapt->note = mem_strdup(in->note);
@@ -207,7 +255,7 @@ void recur_apoint_free(struct recur_apoint *rapt)
mem_free(rapt->note);
if (rapt->rpt)
mem_free(rapt->rpt);
- free_exc_list(&rapt->exc);
+ recur_free_exc_list(&rapt->exc);
mem_free(rapt);
}
@@ -218,7 +266,7 @@ void recur_event_free(struct recur_event *rev)
mem_free(rev->note);
if (rev->rpt)
mem_free(rev->rpt);
- free_exc_list(&rev->exc);
+ recur_free_exc_list(&rev->exc);
mem_free(rev);
}
@@ -261,28 +309,31 @@ static int recur_event_cmp(struct recur_event *a, struct recur_event *b)
/* Insert a new recursive appointment in the general linked list */
struct recur_apoint *recur_apoint_new(char *mesg, char *note, time_t start,
- long dur, char state, int type,
- int freq, time_t until,
- llist_t * except)
+ long dur, char state, struct rpt *rpt)
{
struct recur_apoint *rapt =
mem_malloc(sizeof(struct recur_apoint));
- rapt->rpt = mem_malloc(sizeof(struct rpt));
rapt->mesg = mem_strdup(mesg);
rapt->note = (note != NULL) ? mem_strdup(note) : 0;
rapt->start = start;
- rapt->state = state;
rapt->dur = dur;
- rapt->rpt->type = type;
- rapt->rpt->freq = freq;
- rapt->rpt->until = until;
- if (except) {
- exc_dup(&rapt->exc, except);
- free_exc_list(except);
- } else {
- LLIST_INIT(&rapt->exc);
- }
+ rapt->state = state;
+ rapt->rpt = mem_malloc(sizeof(struct rpt));
+ *rapt->rpt = *rpt;
+ recur_int_list_dup(&rapt->rpt->bymonth, &rpt->bymonth);
+ recur_free_int_list(&rpt->bymonth);
+ recur_int_list_dup(&rapt->rpt->bywday, &rpt->bywday);
+ recur_free_int_list(&rpt->bywday);
+ recur_int_list_dup(&rapt->rpt->bymonthday, &rpt->bymonthday);
+ recur_free_int_list(&rpt->bymonthday);
+ /*
+ * Note. The exception dates are in the list rapt->exc.
+ * The (empty) list rapt->rpt->exc is not used.
+ */
+ recur_exc_dup(&rapt->exc, &rpt->exc);
+ recur_free_exc_list(&rpt->exc);
+ LLIST_INIT(&rapt->rpt->exc);
LLIST_TS_LOCK(&recur_alist_p);
LLIST_TS_ADD_SORTED(&recur_alist_p, rapt, recur_apoint_cmp);
@@ -293,25 +344,26 @@ struct recur_apoint *recur_apoint_new(char *mesg, char *note, time_t start,
/* Insert a new recursive event in the general linked list */
struct recur_event *recur_event_new(char *mesg, char *note, time_t day,
- int id, int type, int freq, time_t until,
- llist_t * except)
+ int id, struct rpt *rpt)
{
struct recur_event *rev = mem_malloc(sizeof(struct recur_event));
- rev->rpt = mem_malloc(sizeof(struct rpt));
rev->mesg = mem_strdup(mesg);
rev->note = (note != NULL) ? mem_strdup(note) : 0;
rev->day = day;
rev->id = id;
- rev->rpt->type = type;
- rev->rpt->freq = freq;
- rev->rpt->until = until;
- if (except) {
- exc_dup(&rev->exc, except);
- free_exc_list(except);
- } else {
- LLIST_INIT(&rev->exc);
- }
+ rev->rpt = mem_malloc(sizeof(struct rpt));
+ *rev->rpt = *rpt;
+ recur_int_list_dup(&rev->rpt->bymonth, &rpt->bymonth);
+ recur_free_int_list(&rpt->bymonth);
+ recur_int_list_dup(&rev->rpt->bywday, &rpt->bywday);
+ recur_free_int_list(&rpt->bywday);
+ recur_int_list_dup(&rev->rpt->bymonthday, &rpt->bymonthday);
+ recur_free_int_list(&rpt->bymonthday);
+ /* Similarly as for recurrent appointment. */
+ recur_exc_dup(&rev->exc, &rpt->exc);
+ recur_free_exc_list(&rpt->exc);
+ LLIST_INIT(&rev->rpt->exc);
LLIST_ADD_SORTED(&recur_elist, rev, recur_event_cmp);
@@ -340,8 +392,7 @@ char recur_def2char(enum recur_type define)
recur_char = 'Y';
break;
default:
- EXIT(_("unknown repetition type"));
- return 0;
+ recur_char = 0;
}
return recur_char;
@@ -375,6 +426,39 @@ int recur_char2def(char type)
return recur_def;
}
+/* Write the bymonthday list. */
+static void bymonthday_append(struct string *s, llist_t *l)
+{
+ llist_item_t *i;
+
+ LLIST_FOREACH(l, i) {
+ int *day = LLIST_GET_DATA(i);
+ string_catf(s, " d%d", *day);
+ }
+}
+
+/* Write the bywday list. */
+static void bywday_append(struct string *s, llist_t *l)
+{
+ llist_item_t *i;
+
+ LLIST_FOREACH(l, i) {
+ int *wday = LLIST_GET_DATA(i);
+ string_catf(s, " w%d", *wday);
+ }
+}
+
+/* Write the bymonth list. */
+static void bymonth_append(struct string *s, llist_t *l)
+{
+ llist_item_t *i;
+
+ LLIST_FOREACH(l, i) {
+ int *mon = LLIST_GET_DATA(i);
+ string_catf(s, " m%d", *mon);
+ }
+}
+
/* Write days for which recurrent items should not be repeated. */
static void recur_exc_append(struct string *s, llist_t *lexc)
{
@@ -395,29 +479,25 @@ static void recur_exc_append(struct string *s, llist_t *lexc)
}
/* Load the recursive appointment description */
-struct recur_apoint *recur_apoint_scan(FILE * f, struct tm start,
- struct tm end, char type, int freq,
- struct tm until, char *note,
- llist_t * exc, char state,
- struct item_filter *filter)
+char *recur_apoint_scan(FILE *f, struct tm start, struct tm end,
+ char state, char *note,
+ struct item_filter *filter,
+ struct rpt *rpt)
{
char buf[BUFSIZ], *nl;
- time_t tstart, tend, tuntil;
+ time_t tstart, tend;
struct recur_apoint *rapt = NULL;
int cond;
- EXIT_IF(!check_date(start.tm_year, start.tm_mon, start.tm_mday) ||
- !check_date(end.tm_year, end.tm_mon, end.tm_mday) ||
- !check_time(start.tm_hour, start.tm_min) ||
- !check_time(end.tm_hour, end.tm_min) ||
- (until.tm_year != 0
- && !check_date(until.tm_year, until.tm_mon,
- until.tm_mday)),
- _("date error in appointment"));
+ if (!check_date(start.tm_year, start.tm_mon, start.tm_mday) ||
+ !check_date(end.tm_year, end.tm_mon, end.tm_mday) ||
+ !check_time(start.tm_hour, start.tm_min) ||
+ !check_time(end.tm_hour, end.tm_min))
+ return _("illegal date in appointment");
/* Read the appointment description */
if (!fgets(buf, sizeof buf, f))
- return NULL;
+ return _("error in appointment description");
nl = strchr(buf, '\n');
if (nl) {
@@ -432,19 +512,14 @@ struct recur_apoint *recur_apoint_scan(FILE * f, struct tm start,
tstart = mktime(&start);
tend = mktime(&end);
- if (until.tm_year != 0) {
- until.tm_hour = 0;
- until.tm_min = 0;
- until.tm_sec = 0;
- until.tm_isdst = -1;
- until.tm_year -= 1900;
- until.tm_mon--;
- tuntil = mktime(&until);
- } else {
- tuntil = 0;
- }
- EXIT_IF(tstart == -1 || tend == -1 || tstart > tend
- || tuntil == -1, _("date error in appointment"));
+ if (tstart == -1 || tend == -1 || tstart > tend)
+ return _("date error in appointment");
+
+ /* Does it occur on the start day? */
+ if (!recur_item_find_occurrence(tstart, tend - tstart, rpt, NULL,
+ update_time_in_date(tstart, 0, 0),
+ NULL))
+ return _("recurrence error: not on start day");
/* Filter item. */
if (filter) {
@@ -458,9 +533,8 @@ struct recur_apoint *recur_apoint_scan(FILE * f, struct tm start,
);
if (filter->hash) {
rapt = recur_apoint_new(buf, note, tstart,
- tend - tstart, state,
- recur_char2def(type),
- freq, tuntil, exc);
+ tend - tstart, state,
+ rpt);
char *hash = recur_apoint_hash(rapt);
cond = cond || !hash_matches(filter->hash, hash);
mem_free(hash);
@@ -473,54 +547,50 @@ struct recur_apoint *recur_apoint_scan(FILE * f, struct tm start,
}
}
if (!rapt)
- rapt = recur_apoint_new(buf, note, tstart, tend - tstart,
- state, recur_char2def(type), freq,
- tuntil, exc);
-
- return rapt;
+ rapt = recur_apoint_new(buf, note, tstart, tend - tstart, state,
+ rpt);
+ return NULL;
}
/* Load the recursive events from file */
-struct recur_event *recur_event_scan(FILE * f, struct tm start, int id,
- char type, int freq, struct tm until,
- char *note, llist_t * exc,
- struct item_filter *filter)
+char *recur_event_scan(FILE * f, struct tm start, int id,
+ char *note, struct item_filter *filter,
+ struct rpt *rpt)
{
char buf[BUFSIZ], *nl;
- time_t tstart, tend, tuntil;
+ time_t tstart, tend;
struct recur_event *rev = NULL;
int cond;
- EXIT_IF(!check_date(start.tm_year, start.tm_mon, start.tm_mday) ||
- !check_time(start.tm_hour, start.tm_min) ||
- (until.tm_year != 0
- && !check_date(until.tm_year, until.tm_mon,
- until.tm_mday)), _("date error in event"));
+ if (!check_date(start.tm_year, start.tm_mon, start.tm_mday) ||
+ !check_time(start.tm_hour, start.tm_min))
+ return _("illegel date in event");
/* Read the event description */
if (!fgets(buf, sizeof buf, f))
- return NULL;
+ return _("error in appointment description");
nl = strchr(buf, '\n');
if (nl) {
*nl = '\0';
}
- start.tm_hour = until.tm_hour = 0;
- start.tm_min = until.tm_min = 0;
- start.tm_sec = until.tm_sec = 0;
- start.tm_isdst = until.tm_isdst = -1;
+ start.tm_hour = 0;
+ start.tm_min = 0;
+ start.tm_sec = 0;
+ start.tm_isdst = -1;
start.tm_year -= 1900;
start.tm_mon--;
- if (until.tm_year != 0) {
- until.tm_year -= 1900;
- until.tm_mon--;
- tuntil = mktime(&until);
- } else {
- tuntil = 0;
- }
+
tstart = mktime(&start);
- EXIT_IF(tstart == -1 || tuntil == -1, _("date error in event"));
- tend = tstart + DAYINSEC - 1;
+ if (tstart == -1)
+ return _("date error in event");
+ tend = ENDOFDAY(tstart);
+
+ /* Does it occur on the start day? */
+ if (!recur_item_find_occurrence(tstart, -1, rpt, NULL,
+ update_time_in_date(tstart, 0, 0),
+ NULL))
+ return _("recurrence error: not on start day");
/* Filter item. */
if (filter) {
@@ -534,8 +604,7 @@ struct recur_event *recur_event_scan(FILE * f, struct tm start, int id,
);
if (filter->hash) {
rev = recur_event_new(buf, note, tstart, id,
- recur_char2def(type),
- freq, tuntil, exc);
+ rpt);
char *hash = recur_event_hash(rev);
cond = cond || !hash_matches(filter->hash, hash);
mem_free(hash);
@@ -548,11 +617,8 @@ struct recur_event *recur_event_scan(FILE * f, struct tm start, int id,
}
}
if (!rev)
- rev = recur_event_new(buf, note, tstart, id,
- recur_char2def(type),
- freq, tuntil, exc);
-
- return rev;
+ rev = recur_event_new(buf, note, tstart, id, rpt);
+ return NULL;
}
char *recur_apoint_tostr(struct recur_apoint *o)
@@ -584,6 +650,9 @@ char *recur_apoint_tostr(struct recur_apoint *o)
recur_def2char(o->rpt->type), lt.tm_mon + 1,
lt.tm_mday, 1900 + lt.tm_year);
}
+ bymonthday_append(&s, &o->rpt->bymonthday);
+ bywday_append(&s, &o->rpt->bywday);
+ bymonth_append(&s, &o->rpt->bymonth);
recur_exc_append(&s, &o->exc);
string_catf(&s, "} ");
if (o->note)
@@ -645,6 +714,9 @@ char *recur_event_tostr(struct recur_event *o)
recur_def2char(o->rpt->type), end_mon, end_day,
end_year);
}
+ bymonthday_append(&s, &o->rpt->bymonthday);
+ bywday_append(&s, &o->rpt->bywday);
+ bymonth_append(&s, &o->rpt->bymonth);
recur_exc_append(&s, &o->exc);
string_catf(&s, "} ");
if (o->note)
@@ -690,6 +762,20 @@ void recur_save_data(FILE * f)
}
/*
+ * Return the month day counted from the opposite end of the month.
+ */
+static int opp_mday(int year, int month, int day)
+{
+ EXIT_IF(day == 0, _("month day is zero"));
+
+ int m_days = days[month - 1] + (month == 2 && ISLEAP(year));
+ if (day > 0)
+ return day - 1 - m_days;
+ else
+ return day + 1 + m_days;
+}
+
+/*
* The two following defines together with the diff_days, diff_months and
* diff_years functions were provided by Lukas Fleischer to correct the wrong
* calculation of recurrent dates after a turn of year.
@@ -740,169 +826,733 @@ static long diff_years(struct tm lt_start, struct tm lt_end)
return lt_end.tm_year - lt_start.tm_year;
}
-static int exc_inday(struct excp *exc, time_t *day_start)
+/*
+ * Return true if 'mon' and 'mday' is month and day of t
+ * (after a call of mktime()).
+ */
+static int date_chk(time_t t, int mon, int mday)
{
- return (date_cmp_day(exc->st, *day_start) == 0);
+ struct tm tm;
+
+ localtime_r(&t, &tm);
+
+ return tm.tm_mon == mon && tm.tm_mday == mday;
}
/*
- * Check if the recurrent item belongs to the selected day, and if yes, store
- * the start date of the occurrence that belongs to the day in a buffer.
- *
- * 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.
+ * Return true if the rrule (start, dur, rpt, exc) has an occurrence on the
+ * given day. If so, save that occurrence in a (dynamic or static) buffer.
*/
-unsigned
-recur_item_find_occurrence(time_t item_start, long item_dur,
- llist_t * item_exc, int rpt_type, int rpt_freq,
- time_t rpt_until, time_t day_start,
- time_t *occurrence)
+static int find_occurrence(time_t start, long dur, struct rpt *rpt, llist_t *exc,
+ time_t day, time_t *occurrence)
{
-/*
- * Function-internal duration
- * 1) To avoid an item ending on midnight (which belongs to the next day),
- * duration is always diminished by 1 second.
- * 2) An event has no explicit duration, but lasts for an entire day, which
- * in turn depends on DST.
- */
-#define ITEM_DUR(d) ((item_dur == -1 ? DAYLEN(d) : item_dur) - 1)
+ /*
+ * Duration-on-day-d fix.
+ * An item cannot end on midnight or else it is counted towards the next day.
+ * An event (dur == -1) has no explicit duration, but is considered to last for
+ * the entire day (d) which depends on DST.
+ */
+#define DUR(d) (dur == -1 ? DAYLEN((d)) - 1 : dur - 1)
long diff;
- struct tm lt_day, lt_item, lt_item_day;
- time_t occ, item_day_start;
-
- item_day_start = update_time_in_date(item_start, 0, 0);
+ struct tm lt_day, lt_start, lt_occur;
+ time_t t;
+ int mday, order, pwday, nwday, mon;
- if (day_start < item_day_start)
+ /* Is the given day before the day of the first occurence? */
+ if (date_cmp_day(day, start) < 0)
return 0;
- if (rpt_until && day_start >=
- rpt_until + (item_start - item_day_start) + ITEM_DUR(rpt_until))
+ /*
+ * - or after the day of the last occurrence (which may stretch beyond
+ * the until date)? Extraneous days are eliminated later.
+ */
+ if (rpt->until &&
+ date_cmp_day(NEXTDAY(rpt->until) + DUR(rpt->until), day) < 0)
return 0;
- localtime_r(&day_start, &lt_day); /* selected day */
- localtime_r(&item_start, &lt_item); /* first occurrence */
- lt_item_day = lt_item; /* recent occurrence */
+ localtime_r(&day, &lt_day); /* Given day. */
+ localtime_r(&start, &lt_start); /* Original item. */
+ lt_occur = lt_start; /* First occurence. */
/*
* Update to the most recent occurrence before or on the selected day.
*/
- switch (rpt_type) {
+ switch (rpt->type) {
case RECUR_DAILY:
- diff = diff_days(lt_item_day, lt_day) % rpt_freq;
- lt_item_day.tm_mday = lt_day.tm_mday - diff;
- lt_item_day.tm_mon = lt_day.tm_mon;
- lt_item_day.tm_year = lt_day.tm_year;
+ /* Number of days since the most recent occurrence. */
+ diff = diff_days(lt_occur, lt_day) % rpt->freq;
+ lt_occur.tm_mday = lt_day.tm_mday - diff;
+ lt_occur.tm_mon = lt_day.tm_mon;
+ lt_occur.tm_year = lt_day.tm_year;
break;
case RECUR_WEEKLY:
- diff = diff_days(lt_item_day, lt_day) %
- (rpt_freq * WEEKINDAYS);
- lt_item_day.tm_mday = lt_day.tm_mday - diff;
- lt_item_day.tm_mon = lt_day.tm_mon;
- lt_item_day.tm_year = lt_day.tm_year;
+ diff = diff_days(lt_occur, lt_day) %
+ (rpt->freq * WEEKINDAYS);
+ lt_occur.tm_mday = lt_day.tm_mday - diff;
+ lt_occur.tm_mon = lt_day.tm_mon;
+ lt_occur.tm_year = lt_day.tm_year;
break;
case RECUR_MONTHLY:
- diff = diff_months(lt_item_day, lt_day) % rpt_freq;
- 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;
+ diff = diff_months(lt_occur, lt_day) % rpt->freq;
+ if (!diff && lt_day.tm_mday < lt_occur.tm_mday)
+ diff += rpt->freq;
+ lt_occur.tm_mon = lt_day.tm_mon - diff;
+ lt_occur.tm_year = lt_day.tm_year;
break;
case RECUR_YEARLY:
- diff = diff_years(lt_item_day, lt_day) % rpt_freq;
+ diff = diff_years(lt_occur, lt_day) % rpt->freq;
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 += rpt_freq;
- lt_item_day.tm_year = lt_day.tm_year - diff;
+ (lt_day.tm_mon < lt_occur.tm_mon ||
+ (lt_day.tm_mon == lt_occur.tm_mon &&
+ lt_day.tm_mday < lt_occur.tm_mday)))
+ diff += rpt->freq;
+ lt_occur.tm_year = lt_day.tm_year - diff;
break;
default:
EXIT(_("unknown item type"));
}
/* Switch to calendar (Unix) time. */
- lt_item_day.tm_isdst = -1;
- occ = mktime(&lt_item_day);
+ lt_occur.tm_isdst = -1;
+ t = mktime(&lt_occur);
/*
* Impossible dates must be ignored (according to RFC 5545). Changing
* only the year or the month may lead to dates like 29 February in
* non-leap years or 31 November.
*/
- if (rpt_type == RECUR_MONTHLY || rpt_type == RECUR_YEARLY) {
- localtime_r(&occ, &lt_item_day);
- if (lt_item_day.tm_mday != lt_item.tm_mday)
+ if ((rpt->type == RECUR_MONTHLY || rpt->type == RECUR_YEARLY) &&
+ !date_chk(t, lt_occur.tm_mon, lt_start.tm_mday))
+ return 0;
+
+ /*
+ * BYMONTHDAY reduction
+ * A month day has two possible list forms.
+ */
+ mday = opp_mday(lt_occur.tm_year + 1900, lt_occur.tm_mon + 1,
+ lt_occur.tm_mday);
+ if (rpt->bymonthday.head &&
+ rpt->type == RECUR_DAILY &&
+ !LLIST_FIND_FIRST(&rpt->bymonthday, &lt_occur.tm_mday, int_cmp) &&
+ !LLIST_FIND_FIRST(&rpt->bymonthday, &mday, int_cmp))
+ return 0;
+
+ /* BYDAY reduction for DAILY */
+ if (rpt->bywday.head && rpt->type == RECUR_DAILY &&
+ !LLIST_FIND_FIRST(&rpt->bywday, &lt_occur.tm_wday, int_cmp))
+ return 0;
+
+ /*
+ * BYDAY reduction for MONTHLY
+ * A weekday has three possible list forms.
+ */
+ if (rpt->bywday.head &&
+ rpt->type == RECUR_MONTHLY && rpt->bymonthday.head) {
+ /* positive order */
+ order = (lt_occur.tm_mday + 6) / WEEKINDAYS;
+ pwday = order * WEEKINDAYS + lt_occur.tm_wday;
+ /* negative order */
+ order = order
+ - wday_per_month(lt_occur.tm_mon + 1,
+ lt_occur.tm_year + 1900,
+ lt_occur.tm_wday)
+ - 1;
+ nwday = order * WEEKINDAYS - lt_occur.tm_wday;
+ if (!LLIST_FIND_FIRST(&rpt->bywday, &lt_occur.tm_wday, int_cmp) &&
+ !LLIST_FIND_FIRST(&rpt->bywday, &pwday, int_cmp) &&
+ !LLIST_FIND_FIRST(&rpt->bywday, &nwday, int_cmp))
return 0;
}
+ /*
+ * BYDAY reduction for YEARLY
+ * A weekday has three possible list forms.
+ */
+ if (rpt->bywday.head &&
+ rpt->type == RECUR_YEARLY && rpt->bymonthday.head) {
+ /* positive order */
+ order = lt_occur.tm_yday / WEEKINDAYS;
+ pwday = order * WEEKINDAYS + lt_occur.tm_wday;
+ /* negative order */
+ order = order
+ - wday_per_year(lt_occur.tm_year + 1900,
+ lt_occur.tm_wday)
+ - 1;
+ nwday = order * WEEKINDAYS - lt_occur.tm_wday;
+ if (!LLIST_FIND_FIRST(&rpt->bywday, &lt_occur.tm_wday, int_cmp) &&
+ !LLIST_FIND_FIRST(&rpt->bywday, &pwday, int_cmp) &&
+ !LLIST_FIND_FIRST(&rpt->bywday, &nwday, int_cmp))
+ return 0;
+ }
+
+ /* BYMONTH reduction */
+ mon = lt_occur.tm_mon + 1;
+ if (rpt->bymonth.head &&
+ rpt->type != RECUR_YEARLY &&
+ !LLIST_FIND_FIRST(&rpt->bymonth, &mon, int_cmp))
+ return 0;
+
/* Exception day? */
- if (LLIST_FIND_FIRST(item_exc, &occ, exc_inday))
+ if (exc && LLIST_FIND_FIRST(exc, &t, exc_inday))
return 0;
- /* After until day? */
- if (rpt_until && occ >= NEXTDAY(rpt_until))
+ /* Extraneous day? */
+ if (rpt->until && t >= NEXTDAY(rpt->until))
return 0;
- /* Does it span the selected day? */
- if (occ + ITEM_DUR(occ) < day_start)
+ /* Does it span the given day? */
+ if (t + DUR(t) < day)
return 0;
if (occurrence)
- *occurrence = occ;
+ *occurrence = t;
return 1;
-#undef ITEM_DUR
}
+#undef DUR
+
+/*
+ * Return true if the rrule (s, d, r, e) has an occurrence, depending
+ * on the frequency, in the year, month or week of day.
+ */
+static int freq_chk(time_t day, time_t s, long d, struct rpt *r, llist_t *e)
+{
+ if (r->type == RECUR_DAILY)
+ EXIT(_("no daily frequency check"));
+
+ struct tm tm_start, tm_day;
+ struct rpt fc_rpt;
+ time_t fc_day, fc_s;
+
+ localtime_r(&s, &tm_start);
+ localtime_r(&day, &tm_day);
+
+ if (r->type == RECUR_WEEKLY) {
+ /* Set day to the weekly occurrence. */
+ fc_day = date_sec_change(
+ day,
+ 0,
+ WDAY(tm_start.tm_wday) - WDAY(tm_day.tm_wday)
+ );
+ fc_s = s;
+ } else {
+ /* The start day may be invalid in some months. */
+ tm_day.tm_mday = tm_start.tm_mday = 1;
+ if (r->type == RECUR_YEARLY)
+ tm_day.tm_mon = tm_start.tm_mon;
+ tm_day.tm_isdst = tm_start.tm_isdst = -1;
+ fc_day = mktime(&tm_day);
+ fc_s = mktime(&tm_start);
+ }
+ /* Turn all reductions off. */
+ fc_rpt = *r;
+ fc_rpt.until = 0;
+ fc_rpt.bymonth.head = fc_rpt.bywday.head = fc_rpt.bymonthday.head = NULL;
+
+ return find_occurrence(fc_s, d, &fc_rpt, e, fc_day, NULL);
+}
+
+/*
+ * Return true if the rrule (s, d, r, e) has an occurrence on 'day' after
+ * 'first'; if so, return it in occurrence.
+ */
+static int test_occurrence(time_t s, long d, struct rpt *r, llist_t *e,
+ time_t first, time_t day, time_t *occurrence)
+{
+ time_t occ;
+
+ if (find_occurrence(s, d, r, e, day, &occ)) {
+ if (occ < first)
+ return 0;
+ if (occurrence)
+ *occurrence = occ;
+ return 1;
+ }
+ return 0;
+}
+
+#define NO_EXPANSION -1
+static int expand_weekly(time_t start, long dur, struct rpt *rpt, llist_t *exc,
+ time_t day, time_t *occurrence)
+{
+ struct tm tm_start;
+ llist_item_t *i;
+ int *w;
+ time_t w_start;
+
+ localtime_r(&start, &tm_start);
+
+ /* BYDAY expansion */
+ if (rpt->bywday.head) {
+ LLIST_FOREACH(&rpt->bywday, i) {
+ w = LLIST_GET_DATA(i);
+ if (*w < 0 || *w > 6)
+ continue;
+ /*
+ * Modify rrule start with a new day in the same week as
+ * start - taking first day of the week into account.
+ */
+ w_start = date_sec_change(
+ start,
+ 0,
+ WDAY(*w) - WDAY(tm_start.tm_wday)
+ );
+ if (test_occurrence(w_start, dur, rpt, exc,
+ start, day, occurrence))
+ return 1;
+ }
+ } else
+ return NO_EXPANSION;
+
+ /* No occurrence */
+ return 0;
+}
+
+static int expand_monthly(time_t start, long dur, struct rpt *rpt, llist_t *exc,
+ time_t day, time_t *occurrence)
+{
+ struct tm tm_start, tm_day;
+ llist_item_t *i;
+ int *w, mday, mon, valid;
+ time_t nstart;
+ struct rpt r = *rpt;
+
+ localtime_r(&day, &tm_day);
+
+ /*
+ * The following three conditional alternatives are mutually exclusive
+ * and cover all four cases of two booleans.
+ */
+
+ /* BYMONTHDAY expansion */
+ if (rpt->bymonthday.head) {
+ LLIST_FOREACH(&rpt->bymonthday, i) {
+ mday = *(int *)LLIST_GET_DATA(i);
+
+ if (mday < 0)
+ mday = opp_mday(tm_day.tm_year + 1900,
+ tm_day.tm_mon + 1, mday);
+ /*
+ * Modify rrule start with a new monthday.
+ * If it is invalid (29, 30 or 31) in the start month,
+ * the month is changed to an earlier one matching the
+ * frequency.
+ */
+ localtime_r(&start, &tm_start);
+ mon = tm_start.tm_mon;
+
+ tm_start.tm_mday = mday;
+ tm_start.tm_isdst = -1;
+ nstart = mktime(&tm_start);
+ valid = date_chk(nstart, mon, mday);
+ /* Never valid? */
+ if (!valid && !(rpt->freq % 12))
+ return 0;
+ /* Note. The loop will terminate! */
+ while (!valid) {
+ localtime_r(&start, &tm_start);
+ mon -= rpt->freq;
+ tm_start.tm_mon = mon;
+ tm_start.tm_mday = mday;
+ tm_start.tm_isdst = -1;
+ nstart = mktime(&tm_start);
+ valid = date_chk(nstart, (mon + 12) % 12, mday);
+ }
+ if (test_occurrence(nstart, dur, rpt, exc,
+ start, day, occurrence))
+ return 1;
+ }
+ }
+ /* BYDAY special expansion for MONTHLY */
+ else if (rpt->bywday.head) {
+ /* The frequency is modified later. */
+ if (!freq_chk(day, start, dur, rpt, exc))
+ return 0;
+
+ LLIST_FOREACH(&rpt->bywday, i) {
+ w = LLIST_GET_DATA(i);
+
+ int order, wday, nbwd;
+
+ localtime_r(&start, &tm_start);
+ /*
+ * Construct a weekly rrule; BYMONTH-reduction in
+ * find_occurrence() will reduce to the bymonth list.
+ */
+ r.type = RECUR_WEEKLY;
+ if (*w > 6) {
+ /*
+ * A single occurrence counting forwards from
+ * the start of the month.
+ */
+ order = *w / WEEKINDAYS;
+ wday = *w % WEEKINDAYS;
+ nbwd = wday_per_month(tm_day.tm_mon + 1,
+ tm_day.tm_year + 1900,
+ wday);
+ if (nbwd < order)
+ return 0;
+ r.freq = order;
+ tm_start.tm_mday = 1;
+ tm_start.tm_mon = tm_day.tm_mon;
+ tm_start.tm_year = tm_day.tm_year;
+ tm_start.tm_isdst = -1;
+ /* Start in the week before the month. */
+ nstart = date_sec_change(
+ next_wday(mktime(&tm_start), wday),
+ 0,
+ -WEEKINDAYS
+ );
+ r.until = date_sec_change(
+ update_time_in_date(nstart, 0, 0),
+ 0,
+ r.freq * WEEKINDAYS
+ );
+ if (rpt->until && r.until > rpt->until)
+ return 0;
+ } else if (*w > -1) {
+ /* Expansion to each week. */
+ wday = *w % WEEKINDAYS;
+ r.freq = 1;
+ nstart = next_wday(start, wday);
+ } else if (*w < -6) {
+ /*
+ * A single ocurrence counting backwards from
+ * the end of the month.
+ */
+ order = -(*w) / WEEKINDAYS;
+ wday = -(*w) % WEEKINDAYS;
+ nbwd = wday_per_month(tm_day.tm_mon + 1,
+ tm_day.tm_year + 1900,
+ wday);
+ if (nbwd < order)
+ return 0;
+ r.freq = nbwd - order + 1;
+ tm_start.tm_mday = 1;
+ tm_start.tm_mon = tm_day.tm_mon;
+ tm_start.tm_year = tm_day.tm_year;
+ tm_start.tm_isdst = -1;
+ nstart = date_sec_change(
+ next_wday(mktime(&tm_start), wday),
+ 0,
+ -WEEKINDAYS
+ );
+ r.until = date_sec_change(
+ update_time_in_date(nstart, 0, 0),
+ 0,
+ r.freq * WEEKINDAYS
+ );
+ if (rpt->until && r.until > rpt->until)
+ return 0;
+ } else
+ EXIT(_("illegal BYDAY value"));
+
+ if (test_occurrence(nstart, dur, &r, exc,
+ start, day, occurrence))
+ return 1;
+ }
+ }
+ else
+ return NO_EXPANSION;
+
+ /* No occurrence */
+ return 0;
+}
+
+static int expand_yearly(time_t start, long dur, struct rpt *rpt, llist_t *exc,
+ time_t day, time_t *occurrence)
+{
+ struct tm tm_start, tm_day;
+ llist_item_t *i, *j;
+ int *m, *w, mday, wday, order, nbwd;
+ time_t nstart;
+ struct rpt r;
+
+ localtime_r(&day, &tm_day);
+ /*
+ * The following five conditional alternatives are mutually exclusive
+ * and cover all eight cases of three booleans.
+ */
+ /* BYMONTH expansion */
+ if (rpt->bymonth.head && !rpt->bymonthday.head && !rpt->bywday.head) {
+ LLIST_FOREACH(&rpt->bymonth, i) {
+ m = LLIST_GET_DATA(i);
+
+ /* Modify rrule start with new month. */
+ localtime_r(&start, &tm_start);
+ tm_start.tm_mon = *m - 1;
+ tm_start.tm_isdst = -1;
+ nstart = mktime(&tm_start);
+ if (!date_chk(nstart, *m - 1, tm_start.tm_mday))
+ continue;
+ if (find_occurrence(nstart, dur, rpt, exc, day,
+ occurrence))
+ return 1;
+ }
+ } else
+ /* BYDAY special expansion for MONTHLY or YEARLY */
+ if (!rpt->bymonthday.head && rpt->bywday.head) {
+ /* Check needed because frequency is modified later. */
+ if (!freq_chk(day, start, dur, rpt, exc))
+ return 0;
+
+ LLIST_FOREACH(&rpt->bywday, i) {
+ w = LLIST_GET_DATA(i);
+
+ localtime_r(&start, &tm_start);
+ /*
+ * Construct a suitable weekly rrule. BYMONTH
+ * reduction in find_occurrence() will limit
+ * occurrences if needed.
+ */
+ r = *rpt;
+ r.type = RECUR_WEEKLY;
+ if (*w > 6) {
+ /*
+ * Special expand: A single ocurrence counting
+ * forward from the start of the month/year.
+ * Start in the week before with a frequency
+ * that matches the ordered weekday and with
+ * until day that allows only one occurrence.
+ */
+ order = *w / WEEKINDAYS;
+ wday = *w % WEEKINDAYS;
+ if (rpt->bymonth.head)
+ nbwd = wday_per_month(
+ tm_day.tm_mon + 1,
+ tm_day.tm_year + 1900,
+ wday
+ );
+ else
+ nbwd = wday_per_year(
+ tm_day.tm_year + 1900,
+ wday
+ );
+ if (nbwd < order)
+ return 0;
+ r.freq = order;
+ tm_start.tm_mday = 1;
+ if (rpt->bymonth.head)
+ tm_start.tm_mon = tm_day.tm_mon;
+ else
+ tm_start.tm_mon = 0;
+ tm_start.tm_year = tm_day.tm_year;
+ tm_start.tm_isdst = -1;
+ nstart = date_sec_change(
+ next_wday(mktime(&tm_start), wday),
+ 0,
+ -WEEKINDAYS
+ );
+ r.until = date_sec_change(
+ update_time_in_date(nstart, 0, 0),
+ 0,
+ r.freq * WEEKINDAYS
+ );
+ if (rpt->until && r.until > rpt->until)
+ return 0;
+ } else if (*w > -1) {
+ /* Expand to each week of the month/year. */
+ wday = *w % WEEKINDAYS;
+ r.freq = 1;
+ nstart = next_wday(start, wday);
+ } else if (*w < -6) {
+ /*
+ * Special expand: A single ocurrence counting
+ * backward from the end of the month/year.
+ */
+ order = -(*w) / WEEKINDAYS;
+ wday = -(*w) % WEEKINDAYS;
+ if (rpt->bymonth.head)
+ nbwd = wday_per_month(
+ tm_day.tm_mon + 1,
+ tm_day.tm_year + 1900,
+ wday
+ );
+ else
+ nbwd = wday_per_year(
+ tm_day.tm_year + 1900,
+ wday
+ );
+ if (nbwd < order)
+ return 0;
+ r.freq = nbwd - order + 1;
+ tm_start.tm_mday = 1;
+ if (rpt->bymonth.head)
+ tm_start.tm_mon = tm_day.tm_mon;
+ else
+ tm_start.tm_mon = 0;
+ tm_start.tm_year = tm_day.tm_year;
+ tm_start.tm_isdst = -1;
+ nstart = date_sec_change(
+ next_wday(mktime(&tm_start), wday),
+ 0,
+ -WEEKINDAYS
+ );
+ r.until = date_sec_change(
+ update_time_in_date(nstart, 0, 0),
+ 0,
+ r.freq * WEEKINDAYS
+ );
+ if (rpt->until && r.until > rpt->until)
+ return 0;
+ } else
+ EXIT(_("illegal BYDAY value"));
+
+ if (test_occurrence(nstart, dur, &r, exc,
+ start, day, occurrence))
+ return 1;
+ }
+ } else
+ /* BYMONTHDAY expansion */
+ if (!rpt->bymonth.head && rpt->bymonthday.head) {
+ LLIST_FOREACH(&rpt->bymonthday, i) {
+ mday = *(int *)LLIST_GET_DATA(i);
+ if (mday < 0)
+ mday = opp_mday(
+ tm_day.tm_year + 1900,
+ tm_day.tm_mon + 1, mday
+ );
+ /* Modify rrule start with new monthday. */
+ localtime_r(&start, &tm_start);
+ tm_start.tm_mday = mday;
+ tm_start.tm_isdst = -1;
+ nstart = mktime(&tm_start);
+ if (!date_chk(nstart, tm_start.tm_mon, mday))
+ continue;
+ if (find_occurrence(nstart, dur, rpt, exc, day,
+ occurrence))
+ return 1;
+ }
+ } else
+ /* BYMONTH and BYMONTHDAY expansion */
+ if (rpt->bymonth.head && rpt->bymonthday.head) {
+ LLIST_FOREACH(&rpt->bymonth, i) {
+ m = LLIST_GET_DATA(i);
+
+ LLIST_FOREACH(&rpt->bymonthday, j) {
+ mday = *(int *)LLIST_GET_DATA(j);
+ if (mday < 0)
+ mday = opp_mday(
+ tm_day.tm_year + 1900,
+ tm_day.tm_mon + 1, mday
+ );
+ /* Modify start with new monthday and month. */
+ localtime_r(&start, &tm_start);
+ /* Number of days in February! */
+ if (*m == 2 && mday == 29 &&
+ !ISLEAP(tm_start.tm_year + 1900) &&
+ rpt->freq % 4) {
+ if (!freq_chk(day, start, dur, rpt, exc))
+ return 0;
+ tm_start.tm_year -= tm_start.tm_year % 4;
+ }
+ tm_start.tm_mday = mday;
+ tm_start.tm_mon = *m - 1;
+ tm_start.tm_isdst = -1;
+ nstart = mktime(&tm_start);
+ if (!date_chk(nstart, *m - 1, mday))
+ continue;
+ if (find_occurrence(nstart, dur, rpt, exc, day,
+ occurrence))
+ return 1;
+ }
+ }
+ } else
+ return NO_EXPANSION;
+
+ /* No occurrence */
+ return 0;
+}
+
+/*
+ * Membership test for the recurrence set of the rrule (start, dur, rpt, exc).
+ *
+ * Return true if day belongs to the set. If so, the occurrence is saved in a
+ * buffer. A positive result is always the outcome of find_occurrence(), whereas
+ * a negative result may be arrived at in other ways.
+ *
+ * The basic (type, frequency)-check is in find_occurrence(). When recurrence
+ * set expansion and/or reduction (RFC 5545) is needed, expansion is done before
+ * call of find_occurrence(), while reduction takes place in find_occurrence().
+ *
+ * Recurrence set expansion is accomplished by a combination of calls of
+ * find_occurrence(), possibly with change of type, frequency and start.
+ */
+unsigned
+recur_item_find_occurrence(time_t start, long dur, struct rpt *rpt, llist_t *exc,
+ time_t day, time_t *occurrence)
+{
+ int res;
+
+ /* To make it possible to set an earlier start without expanding the
+ * recurrence set. */
+ if (date_cmp_day(day, start) < 0)
+ return 0;
+
+ switch (rpt->type) {
+ case RECUR_DAILY:
+ res = NO_EXPANSION;
+ break;
+ case RECUR_WEEKLY:
+ res = expand_weekly(start, dur, rpt, exc, day, occurrence);
+ break;
+ case RECUR_MONTHLY:
+ res = expand_monthly(start, dur, rpt, exc, day, occurrence);
+ break;
+ case RECUR_YEARLY:
+ res = expand_yearly(start, dur, rpt, exc, day, occurrence);
+ break;
+ default:
+ res = 0;
+ }
+
+ if (res == NO_EXPANSION)
+ return find_occurrence(start, dur, rpt, exc, day, occurrence);
+
+ /* The result of find_occurrence() is passed on. */
+ return res;
+}
+#undef NO_EXPANSION
unsigned
recur_apoint_find_occurrence(struct recur_apoint *rapt, time_t day_start,
time_t *occurrence)
{
- return recur_item_find_occurrence(rapt->start, rapt->dur,
- &rapt->exc, rapt->rpt->type,
- rapt->rpt->freq,
- rapt->rpt->until, day_start,
- occurrence);
+ return recur_item_find_occurrence(rapt->start, rapt->dur, rapt->rpt,
+ &rapt->exc, day_start, occurrence);
}
unsigned
recur_event_find_occurrence(struct recur_event *rev, time_t day_start,
time_t *occurrence)
{
- return recur_item_find_occurrence(rev->day, -1, &rev->exc,
- rev->rpt->type, rev->rpt->freq,
- rev->rpt->until, day_start,
- occurrence);
+ return recur_item_find_occurrence(rev->day, -1, rev->rpt, &rev->exc,
+ day_start, occurrence);
}
/* Check if a recurrent item belongs to the selected day. */
unsigned
-recur_item_inday(time_t item_start, long item_dur, llist_t * item_exc,
- int rpt_type, int rpt_freq, time_t rpt_until,
+recur_item_inday(time_t start, long dur,
+ struct rpt *rpt, llist_t * exc,
time_t day_start)
{
/* We do not need the (real) start time of the occurrence here, so just
* ignore the buffer. */
- return recur_item_find_occurrence(item_start, item_dur, item_exc,
- rpt_type, rpt_freq, rpt_until,
+ return recur_item_find_occurrence(start, dur, rpt, exc,
day_start, NULL);
}
unsigned recur_apoint_inday(struct recur_apoint *rapt, time_t *day_start)
{
- return recur_item_inday(rapt->start, rapt->dur, &rapt->exc,
- rapt->rpt->type, rapt->rpt->freq,
- rapt->rpt->until, *day_start);
+ return recur_item_inday(rapt->start, rapt->dur, rapt->rpt, &rapt->exc,
+ *day_start);
}
unsigned recur_event_inday(struct recur_event *rev, time_t *day_start)
{
- return recur_item_inday(rev->day, -1, &rev->exc,
- rev->rpt->type, rev->rpt->freq,
- rev->rpt->until, *day_start);
+ return recur_item_inday(rev->day, -1, rev->rpt, &rev->exc,
+ *day_start);
}
/* Add an exception to a recurrent event. */
@@ -960,6 +1610,62 @@ void recur_apoint_erase(struct recur_apoint *rapt)
LLIST_TS_UNLOCK(&recur_alist_p);
}
+/* Read monthday list. */
+void recur_bymonthday(llist_t *l, FILE *data_file)
+{
+ int c = 0, d;
+
+ LLIST_INIT(l);
+ while ((c = getc(data_file)) == 'd') {
+ ungetc(c, data_file);
+ if (fscanf(data_file, "d%d ", &d) != 1)
+ EXIT(_("syntax error in bymonthday"));
+ int *i = mem_malloc(sizeof(int));
+ *i = d;
+ LLIST_ADD(l, i);
+ }
+ ungetc(c, data_file);
+}
+
+/* Read weekday list. */
+void recur_bywday(enum recur_type type, llist_t *l, FILE *data_file)
+{
+ int c = 0, w;
+
+ type = !(type == RECUR_MONTHLY || type == RECUR_YEARLY);
+
+ LLIST_INIT(l);
+ while ((c = getc(data_file)) == 'w') {
+ ungetc(c, data_file);
+ if (fscanf(data_file, "w%d ", &w) != 1)
+ EXIT(_("syntax error in bywday"));
+ if (type && (w < 0 || w > 6))
+ EXIT(_("illegal BYDAY value"));
+ int *i = mem_malloc(sizeof(int));
+ *i = w;
+ LLIST_ADD(l, i);
+ }
+ ungetc(c, data_file);
+}
+
+/* Read month list. */
+void recur_bymonth(llist_t *l, FILE *data_file)
+{
+ int c = 0, m;
+
+ LLIST_INIT(l);
+ while ((c = getc(data_file)) == 'm') {
+ ungetc(c, data_file);
+ if (fscanf(data_file, "m%d ", &m) != 1)
+ EXIT(_("syntax error in bymonth"));
+ EXIT_IF(m < 1 || m > 12, _("illegal bymonth value"));
+ int *i = mem_malloc(sizeof(int));
+ *i = m;
+ LLIST_ADD(l, i);
+ }
+ ungetc(c, data_file);
+}
+
/*
* Read days for which recurrent items must not be repeated
* (such days are called exceptions).
@@ -989,6 +1695,7 @@ void recur_exc_scan(llist_t * lexc, FILE * data_file)
exc->st = mktime(&day);
LLIST_ADD(lexc, exc);
}
+ ungetc(c, data_file);
}
/*
@@ -1088,3 +1795,27 @@ void recur_apoint_paste_item(struct recur_apoint *rapt, time_t date)
if (notify_bar())
notify_check_repeated(rapt);
}
+
+/*
+ * Finds the next occurrence of a recurrent item and returns it in the provided
+ * buffer. Useful for test of a repeated item.
+ */
+int recur_next_occurrence(time_t s, long d, struct rpt *r, llist_t *e,
+ time_t occur, time_t *next)
+{
+ int ret = 0;
+
+ if (r->until && r->until <= occur)
+ return ret;
+
+ while (!r->until || occur < r->until) {
+ occur = NEXTDAY(occur);
+ if (!check_sec(&occur))
+ break;
+ if (recur_item_find_occurrence(s, d, r, e, occur, next)) {
+ ret = 1;
+ break;
+ }
+ }
+ return ret;
+}
diff --git a/src/ui-day.c b/src/ui-day.c
index 7d571fc..5a8d960 100644
--- a/src/ui-day.c
+++ b/src/ui-day.c
@@ -34,6 +34,8 @@
*
*/
+#include <limits.h>
+#include <langinfo.h>
#include "calcurse.h"
/* Cut & paste registers. */
@@ -163,32 +165,44 @@ static time_t day_edit_time(time_t start, long duration, int move)
/*
* Change start time or move an item.
* Input/output: start and dur.
+ * For recurrent items the new start time must match the repetition pattern.
* If move = 0, end time is fixed, and the new duration is calculated
* when the new start time is known.
* If move = 1, duration is fixed, but passed on for validation of new end time.
*/
-static void update_start_time(time_t *start, long *dur, int move)
+static void update_start_time(time_t *start, long *dur, struct rpt *rpt, int move)
{
time_t newtime;
const char *msg_wrong_time =
_("Invalid time: start time must come before end time!");
+ const char *msg_match =
+ _("Repetition must begin on start day.");
const char *msg_enter = _("Press [Enter] to continue");
+ char *msg;
for (;;) {
newtime = day_edit_time(*start, *dur, move);
if (!newtime)
break;
- if (move) {
- *start = newtime;
- break;
+ if (rpt && !recur_item_find_occurrence(
+ newtime, *dur, rpt, NULL,
+ update_time_in_date(newtime, 0, 0),
+ NULL)) {
+ msg = (char *)msg_match;
} else {
- if (newtime <= *start + *dur) {
- *dur -= (newtime - *start);
+ if (move) {
*start = newtime;
break;
+ } else {
+ if (newtime <= *start + *dur) {
+ *dur -= (newtime - *start);
+ *start = newtime;
+ break;
+ }
}
+ msg = (char *)msg_wrong_time;
}
- status_mesg(msg_wrong_time, msg_enter);
+ status_mesg(msg, msg_enter);
keys_wgetch(win[KEY].p);
}
return;
@@ -273,8 +287,8 @@ static void update_desc(char **desc)
updatestring(win[STA].p, desc, 0, 1);
}
-/* Edit the list of exception days for a recurrent item. */
-static int update_exc(llist_t *exc)
+/* Edit a list of exception days for a recurrent item. */
+static int edit_exc(llist_t *exc)
{
int updated = 0;
@@ -288,7 +302,7 @@ static int update_exc(llist_t *exc)
while (1) {
ret = updatestring(win[STA].p, &days, 0, 1);
if (ret == GETSTRING_VALID || ret == GETSTRING_RET) {
- if (recur_update_exc(exc, days)) {
+ if (recur_str2exc(exc, days)) {
updated = 1;
break;
} else {
@@ -304,95 +318,436 @@ static int update_exc(llist_t *exc)
return updated;
}
-static void update_rept(struct rpt **rpt, const time_t start, llist_t *exc)
+/*
+ * Decode an integer representing a weekday or ordered weekday.
+ * The return value is the (abbreviated) localized day name.
+ * The order is returned in the second argument.
+ */
+static char *int2wday(int i, int *ord, int_list_t type)
+{
+ if (type == BYDAY_W ||
+ ((type == BYDAY_M || type == BYDAY_Y) && -1 < i && i < 7))
+ *ord = 0;
+ else if ((type == BYDAY_M && 6 < i && i < 42) ||
+ (type == BYDAY_Y && 6 < i && i < 378))
+ *ord = i / 7;
+ else if ((type == BYDAY_M && -42 < i && i < -6) ||
+ (type == BYDAY_Y && -378 < i && i < -6)) {
+ i = -i;
+ *ord = -(i / 7);
+ } else
+ return NULL;
+
+ return nl_langinfo(ABDAY_1 + i % 7);
+}
+
+/*
+ * Given a (linked) list of integers representing weekdays, monthdays or months.
+ * Return a string containing the weekdays or integers separated by spaces.
+ */
+static char *int2str(llist_t *il, int_list_t type)
+{
+ llist_item_t *i;
+ int *p, ord = 0;
+ char *wday;
+ struct string s;
+
+ string_init(&s);
+ LLIST_FOREACH(il, i) {
+ p = LLIST_GET_DATA(i);
+ wday = int2wday(*p, &ord, type);
+ if (wday)
+ string_catf(&s, ord ? "%d%s " : "%.0d%s ", ord, wday);
+ else
+ string_catf(&s, "%i ", *p);
+ }
+
+ return string_buf(&s);
+}
+
+/*
+ * Encode a weekday or ordered weekday as an integer.
+ */
+static int wday2int(char *s)
+{
+ int i, ord;
+ char *tail;
+
+ i = strtol(s, &tail, 10);
+ if (!i && tail == s)
+ ord = 0;
+ else
+ ord = i > 0 ? i : -i;
+
+ if (!strcmp(tail, nl_langinfo(ABDAY_1)))
+ return (i < 0 ? -1 : 1) * (ord * 7 + 0);
+ else if (!strcmp(tail, nl_langinfo(ABDAY_2)))
+ return (i < 0 ? -1 : 1) * (ord * 7 + 1);
+ else if (!strcmp(tail, nl_langinfo(ABDAY_3)))
+ return (i < 0 ? -1 : 1) * (ord * 7 + 2);
+ else if (!strcmp(tail, nl_langinfo(ABDAY_4)))
+ return (i < 0 ? -1 : 1) * (ord * 7 + 3);
+ else if (!strcmp(tail, nl_langinfo(ABDAY_5)))
+ return (i < 0 ? -1 : 1) * (ord * 7 + 4);
+ else if (!strcmp(tail, nl_langinfo(ABDAY_6)))
+ return (i < 0 ? -1 : 1) * (ord * 7 + 5);
+ else if (!strcmp(tail, nl_langinfo(ABDAY_7)))
+ return (i < 0 ? -1 : 1) * (ord * 7 + 6);
+ else
+ return -1;
+}
+
+/*
+ * Parse an integer or weekday string. Valid values depend on type.
+ * On success the integer or integer code is returned in *i.
+ */
+static int parse_int(char *s, long *i, int_list_t type)
+{
+ char *eos;
+
+ if (type == BYDAY_W || type == BYDAY_M || type == BYDAY_Y) {
+ *i = wday2int(s);
+ if (*i == -1)
+ return 0;
+ } else {
+ *i = strtol(s, &eos, 10);
+ if (*eos || *i > INT_MAX)
+ return 0;
+ }
+
+ switch (type) {
+ case BYMONTH:
+ /* 1,..,12 */
+ if (0 < *i && *i < 13)
+ return 1;
+ break;
+ case BYDAY_W:
+ /* 0,..,6 */
+ if (-1 < *i && *i < 7)
+ return 1;
+ break;
+ case BYDAY_M:
+ /* 0,..,6 or 7,..,41 or -7,..,-41 */
+ /* 41 = 5*7 + 6, i.e. fifth Saturday of the month */
+ if ((-42 < *i && *i < -6) || (-1 < *i && *i < 42))
+ return 1;
+ break;
+ case BYDAY_Y:
+ /* 0,..,6 or 7,..,377 or -7,..,-377 */
+ /* 377 = 53*7 + 6, i.e. 53th Saturday of the year */
+ if ((-378 < *i && *i < -6) || (-1 < *i && *i < 378))
+ return 1;
+ break;
+ case BYMONTHDAY:
+ /* 1,..,31 or -1,..,-31 */
+ if ((0 < *i && *i < 32) || (-32 < *i && *i < 0))
+ return 1;
+ break;
+ default:
+ return 0;
+ }
+ return 0;
+}
+
+/*
+ * Update a (linked) list of integer values from a string of such values. Any
+ * positive number of spaces are allowed before, between and after the values.
+ */
+static int str2int(llist_t *l, char *s, int type) {
+ int *j, updated = 0;
+ char *c;
+ long i;
+ llist_t nl;
+ LLIST_INIT(&nl);
+
+ while (1) {
+ while (*s == ' ')
+ s++;
+ if ((c = strchr(s, ' ')))
+ *c = '\0';
+ else if (!strlen(s))
+ break;
+ if (parse_int(s, &i, type)) {
+ j = mem_malloc(sizeof(int));
+ *j = i;
+ LLIST_ADD(&nl, j);
+ } else
+ goto cleanup;
+ if (c)
+ s = c + 1;
+ else
+ break;
+ }
+ recur_free_int_list(l);
+ recur_int_list_dup(l, &nl);
+ updated = 1;
+cleanup:
+ recur_free_int_list(&nl);
+ return updated;
+}
+
+static void help_ilist(int_list_t list, int rule)
+{
+ char *msg1 = "";
+ char *msg2 = "";
+ char *byday_w_d = _("only on these weekdays");
+ char *byday_w_w = _("also on these weekdays");
+ char *byday_m_m_1 =
+ _("also on these weekdays of month - or only on given monthdays");
+ char *byday_m_m_2 =
+ _("either all weekdays or 1st, 2nd, ... weekday or 1st, 2nd, ... from the end");
+ char *byday_y_y_1 =
+ _("also on these weekdays of year or given months - or only on given monthdays");
+ char *byday_y_y_2 =
+ _("positive: 1st, 2nd,... weekday of month or year, negative: 1st, 2nd,... from end");
+ char *bymonth_dwm =
+ _("only in these months");
+ char *bymonth_y =
+ _("also in these months");
+ char *bymonthday_d = _("only on these days of the month");
+ char *bymonthday_my = _("also on these days of the month");
+
+
+ switch (list) {
+ case BYDAY_W:
+ switch (rule) {
+ case RECUR_DAILY:
+ msg1 = byday_w_d;
+ msg2 = "";
+ break;
+ case RECUR_WEEKLY:
+ msg1 = byday_w_w;
+ msg2 = "";
+ break;
+ default:
+ EXIT("internal inconsistency");
+ }
+ break;
+ case BYDAY_M:
+ switch (rule) {
+ case RECUR_MONTHLY:
+ msg1 = byday_m_m_1;
+ msg2 = byday_m_m_2;
+ break;
+ default:
+ EXIT("internal inconsistency");
+ }
+ break;
+ case BYDAY_Y:
+ switch (rule) {
+ case RECUR_YEARLY:
+ msg1 = byday_y_y_1;
+ msg2 = byday_y_y_2;
+ break;
+ default:
+ EXIT("internal inconsistency");
+ }
+ break;
+ case BYMONTH:
+ switch (rule) {
+ case RECUR_DAILY:
+ case RECUR_WEEKLY:
+ case RECUR_MONTHLY:
+ msg1 = bymonth_dwm;
+ msg2 = "";
+ break;
+ case RECUR_YEARLY:
+ msg1 = bymonth_y;
+ msg2 = "";
+ break;
+ default:
+ break;
+ }
+ break;
+ case BYMONTHDAY:
+ switch (rule) {
+ case RECUR_DAILY:
+ msg1 = bymonthday_d;
+ msg2 = "";
+ break;
+ case RECUR_MONTHLY:
+ case RECUR_YEARLY:
+ msg1 = bymonthday_my;
+ msg2 = "";
+ break;
+ default:
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+ status_mesg(msg1, msg2);
+ keys_wgetch(win[KEY].p);
+}
+
+/* Edit an rrule (linked) list of integers. */
+static int edit_ilist(llist_t *ilist, int_list_t list_type, int rule_type)
{
- /* Pointers to dynamically allocated memory. */
- char *msg_rpt_current = NULL;
- char *msg_rpt_asktype = NULL;
+ char *msg;
+ char *wday = NULL;
+ char *wday_w = _("Weekdays (%s|..|%s), '?' for help:");
+ char *wday_m =
+ _("Weekdays (%1$s|..|%2$s or 1%1$s|..|5%2$s or -1%1$s|..|-5%2$s), '?' for help:");
+ char *wday_y =
+ _("Weekdays (%1$s|..|%2$s or 1%1$s|..|53%2$s or -1%1$s|..|-53%2$s), '?' for help:");
+ char *month = _("Months (1..12), '?' for help:");
+ char *mday = _("Monthdays (1..31 or -1..-31), '?' for help:");
+ char *invalid = _("Invalid format - try again.");
+ char *cont = _("Press any key to continue.");
+ int updated = 0;
+
+ if (list_type == NOLL)
+ return !updated;
+ char *istr;
+ enum getstr ret;
+
+ switch (list_type) {
+ case BYDAY_W:
+ asprintf(&wday, wday_w,
+ nl_langinfo(ABDAY_2), nl_langinfo(ABDAY_1));
+ msg = wday;
+ break;
+ case BYDAY_M:
+ asprintf(&wday, wday_m,
+ nl_langinfo(ABDAY_2), nl_langinfo(ABDAY_1));
+ msg = wday;
+ break;
+ case BYDAY_Y:
+ asprintf(&wday, wday_y,
+ nl_langinfo(ABDAY_2), nl_langinfo(ABDAY_1));
+ msg = wday;
+ break;
+ case BYMONTH:
+ msg = month;
+ break;
+ case BYMONTHDAY:
+ msg = mday;
+ break;
+ default:
+ msg = NULL;
+ break;
+ }
+ status_mesg(msg, "");
+ istr = int2str(ilist, list_type);
+ while (1) {
+ ret = updatestring(win[STA].p, &istr, 0, 1);
+ if (ret == GETSTRING_VALID || ret == GETSTRING_RET) {
+ if (*(istr + strlen(istr) - 1) == '?')
+ help_ilist(list_type, rule_type);
+ else if (str2int(ilist, istr, list_type)) {
+ updated = 1;
+ break;
+ } else {
+ status_mesg(invalid, cont);
+ keys_wgetch(win[KEY].p);
+ }
+ mem_free(istr);
+ status_mesg(msg, "");
+ istr = int2str(ilist, list_type);
+ } else if (ret == GETSTRING_ESC)
+ break;
+ }
+ mem_free(istr);
+ mem_free(wday);
+
+ return updated;
+}
+
+static int update_rept(time_t start, long dur, struct rpt **rpt, llist_t *exc,
+ int simple)
+{
+ int updated = 0;
+ struct rpt nrpt;
+ char *types = NULL;
char *freqstr = NULL;
char *timstr = NULL;
char *outstr = NULL;
+ const char *msg_cont = _("Press any key to continue.");
- /* Update repetition type. */
- int newtype;
- const char *msg_rpt_prefix = _("Enter the new repetition type:");
- const char *msg_rpt_daily = _("(d)aily");
- const char *msg_rpt_weekly = _("(w)eekly");
- const char *msg_rpt_monthly = _("(m)onthly");
- const char *msg_rpt_yearly = _("(y)early");
+ LLIST_INIT(&nrpt.exc);
+ LLIST_INIT(&nrpt.bywday);
+ LLIST_INIT(&nrpt.bymonth);
+ LLIST_INIT(&nrpt.bymonthday);
+
+ /* Edit repetition type. */
+ const char *msg_prefix = _("Repetition type:");
+ const char *daily = _("(d)aily");
+ const char *weekly = _("(w)eekly");
+ const char *monthly = _("(m)onthly");
+ const char *yearly = _("(y)early");
+ const char *dwmy = _("[dwmy]");
/* Find the current repetition type. */
- const char *rpt_current;
+ const char *current;
switch (recur_def2char((*rpt)->type)) {
case 'D':
- rpt_current = msg_rpt_daily;
+ current = daily;
break;
case 'W':
- rpt_current = msg_rpt_weekly;
+ current = weekly;
break;
case 'M':
- rpt_current = msg_rpt_monthly;
+ current = monthly;
break;
case 'Y':
- rpt_current = msg_rpt_yearly;
+ current = yearly;
break;
default:
- /* NOTREACHED, but makes the compiler happier. */
- rpt_current = msg_rpt_daily;
+ /* New item. */
+ current = "";
}
- asprintf(&msg_rpt_current, _("(currently using %s)"), rpt_current);
- asprintf(&msg_rpt_asktype, "%s %s, %s, %s, %s? %s", msg_rpt_prefix,
- msg_rpt_daily, msg_rpt_weekly, msg_rpt_monthly,
- msg_rpt_yearly, msg_rpt_current);
- const char *msg_rpt_choice = _("[dwmy]");
- switch (status_ask_choice(msg_rpt_asktype, msg_rpt_choice, 4)) {
+ asprintf(&types, "%s %s, %s, %s, %s?",
+ msg_prefix, daily, weekly, monthly, yearly);
+ if (current[0])
+ asprintf(&types, "%s (now %s)", types, current);
+ switch (status_ask_choice(types, dwmy, 4)) {
case 1:
- newtype = 'D';
+ nrpt.type = 'D';
break;
case 2:
- newtype = 'W';
+ nrpt.type = 'W';
break;
case 3:
- newtype = 'M';
+ nrpt.type = 'M';
break;
case 4:
- newtype = 'Y';
+ nrpt.type = 'Y';
break;
default:
goto cleanup;
}
+ nrpt.type = recur_char2def(nrpt.type);
- /* Update frequency. */
- int newfreq;
- const char *msg_wrong_freq = _("Invalid frequency.");
- const char *msg_enter = _("Press [Enter] to continue");
+ /* Edit frequency. */
+ const char *msg_freq = _("Repetition frequency:");
+ const char *msg_inv_freq = _("Invalid frequency.");
do {
- status_mesg(_("Enter the repetition frequency:"), "");
+ status_mesg(msg_freq, "");
mem_free(freqstr);
asprintf(&freqstr, "%d", (*rpt)->freq);
if (updatestring(win[STA].p, &freqstr, 0, 1) !=
GETSTRING_VALID) {
goto cleanup;
}
- newfreq = atoi(freqstr);
- if (newfreq == 0) {
- status_mesg(msg_wrong_freq, msg_enter);
+ nrpt.freq = atoi(freqstr);
+ if (nrpt.freq <= 0) {
+ status_mesg(msg_inv_freq, msg_cont);
keys_wait_for_any_key(win[KEY].p);
}
}
- while (newfreq == 0);
+ while (nrpt.freq <= 0);
- /* Update end date. */
- time_t newuntil;
+ /* Edit until date. */
const char *msg_until_1 =
- _("Enter end date or duration ('?' for input formats):");
+ _("Until date or duration ('?' for input formats):");
const char *msg_help_1 =
_("Date: %s (year or month may be omitted). Endless duration: 0.");
const char *msg_help_2 =
_("Duration in days: +dd. Duration in weeks and days: +??w??d.");
- const char *msg_wrong_time =
- _("Invalid date: end date must come after start date (%s).");
- const char *msg_wrong_date = _("Invalid date.");
+ const char *msg_inv_until =
+ _("Invalid date: until date must come after start date (%s).");
+ const char *msg_inv_date = _("Invalid date.");
for (;;) {
mem_free(timstr);
@@ -404,7 +759,7 @@ static void update_rept(struct rpt **rpt, const time_t start, llist_t *exc)
if (updatestring(win[STA].p, &timstr, 0, 1) == GETSTRING_ESC)
goto cleanup;
if (strcmp(timstr, "") == 0 || strcmp(timstr, "0") == 0) {
- newuntil = 0;
+ nrpt.until = 0;
break;
}
if (*(timstr + strlen(timstr) - 1) == '?') {
@@ -417,12 +772,12 @@ static void update_rept(struct rpt **rpt, const time_t start, llist_t *exc)
if (*timstr == '+') {
unsigned days;
if (!parse_date_duration(timstr + 1, &days, start)) {
- status_mesg(msg_wrong_date, msg_enter);
+ status_mesg(msg_inv_date, msg_cont);
keys_wgetch(win[KEY].p);
continue;
}
/* Until is midnight of the day. */
- newuntil = date_sec_change(
+ nrpt.until = date_sec_change(
update_time_in_date(start, 0, 0),
0, days
);
@@ -430,42 +785,122 @@ static void update_rept(struct rpt **rpt, const time_t start, llist_t *exc)
int year, month, day;
if (!parse_date(timstr, conf.input_datefmt, &year,
&month, &day, ui_calendar_get_slctd_day())) {
- status_mesg(msg_wrong_date, msg_enter);
+ status_mesg(msg_inv_date, msg_cont);
keys_wgetch(win[KEY].p);
continue;
}
struct date d = { day, month, year };
- newuntil = date2sec(d, 0, 0);
+ nrpt.until = date2sec(d, 0, 0);
}
/* Conmpare days (midnights) - until-day may equal start day. */
- if (newuntil >= update_time_in_date(start, 0, 0))
+ if (nrpt.until >= update_time_in_date(start, 0, 0))
break;
mem_free(timstr);
mem_free(outstr);
timstr = date_sec2date_str(start, DATEFMT(conf.input_datefmt));
- asprintf(&outstr, msg_wrong_time, timstr);
- status_mesg(outstr, msg_enter);
+ asprintf(&outstr, msg_inv_until, timstr);
+ status_mesg(outstr, msg_cont);
keys_wgetch(win[KEY].p);
}
- /* Update exception list. */
- if (!update_exc(exc))
+ if (simple) {
+ (*rpt)->type = nrpt.type;
+ (*rpt)->freq = nrpt.freq;
+ (*rpt)->until = nrpt.until;
+ updated = 1;
+ goto cleanup;
+ }
+
+ /* Edit exception list. */
+ recur_exc_dup(&nrpt.exc, exc);
+ if (!edit_exc(&nrpt.exc))
+ goto cleanup;
+
+ /* Edit BYDAY list. */
+ int_list_t byday_type;
+ switch (nrpt.type) {
+ case RECUR_DAILY:
+ byday_type = BYDAY_W;
+ break;
+ case RECUR_WEEKLY:
+ byday_type = BYDAY_W;
+ break;
+ case RECUR_MONTHLY:
+ byday_type = BYDAY_M;
+ break;
+ case RECUR_YEARLY:
+ byday_type = BYDAY_Y;
+ break;
+ default:
+ byday_type = NOLL;
+ break;
+ }
+ recur_int_list_dup(&nrpt.bywday, &(*rpt)->bywday);
+ if (!edit_ilist(&nrpt.bywday, byday_type, nrpt.type))
+ goto cleanup;
+
+ /* Edit BYMONTH list. */
+ recur_int_list_dup(&nrpt.bymonth, &(*rpt)->bymonth);
+ if (!edit_ilist(&nrpt.bymonth, BYMONTH, nrpt.type))
+ goto cleanup;
+
+ /* Edit BYMONTHDAY list. */
+ if (nrpt.type != RECUR_WEEKLY) {
+ recur_int_list_dup(&nrpt.bymonthday, &(*rpt)->bymonthday);
+ if (!edit_ilist(&nrpt.bymonthday, BYMONTHDAY, nrpt.type))
+ goto cleanup;
+ }
+
+ /*
+ * Check whether the start occurrence matches the recurrence rule, in
+ * other words, does it occur on the start day? This is required by
+ * RFC5545 and ensures that the recurrence set is non-empty (unless it
+ * is an exception day).
+ */
+ const char *msg_match =
+ _("Repetition must begin on start day; any change discarded.");
+ if (!recur_item_find_occurrence(start, dur, &nrpt, NULL,
+ update_time_in_date(start, 0, 0),
+ NULL)) {
+ status_mesg(msg_match, msg_cont);
+ keys_wgetch(win[KEY].p);
goto cleanup;
+ }
+
+ /* Update all recurrence parameters. */
+ (*rpt)->type = nrpt.type;
+ (*rpt)->freq = nrpt.freq;
+ (*rpt)->until = nrpt.until;
+
+ recur_free_exc_list(exc);
+ recur_exc_dup(exc, &nrpt.exc);
+
+ recur_free_int_list(&(*rpt)->bywday);
+ recur_int_list_dup(&(*rpt)->bywday, &nrpt.bywday);
- (*rpt)->type = recur_char2def(newtype);
- (*rpt)->freq = newfreq;
- (*rpt)->until = newuntil;
+ recur_free_int_list(&(*rpt)->bymonth);
+ recur_int_list_dup(&(*rpt)->bymonth, &nrpt.bymonth);
+ recur_free_int_list(&(*rpt)->bymonthday);
+ recur_int_list_dup(&(*rpt)->bymonthday, &nrpt.bymonthday);
+
+ updated = 1;
cleanup:
- mem_free(msg_rpt_current);
- mem_free(msg_rpt_asktype);
+ mem_free(types);
mem_free(freqstr);
mem_free(timstr);
mem_free(outstr);
+ recur_free_exc_list(&nrpt.exc);
+ recur_free_int_list(&nrpt.bywday);
+ recur_free_int_list(&nrpt.bymonth);
+ recur_free_int_list(&nrpt.bymonthday);
+
+ return updated;
}
/* Edit an already existing item. */
+#define ADVANCED 0
void ui_day_item_edit(void)
{
struct recur_event *re;
@@ -482,7 +917,7 @@ void ui_day_item_edit(void)
switch (p->type) {
case RECUR_EVNT:
re = p->item.rev;
- const char *choice_recur_evnt[2] = {
+ const char *choice_recur_evnt[] = {
_("Description"),
_("Repetition")
};
@@ -490,11 +925,9 @@ void ui_day_item_edit(void)
(_("Edit: "), choice_recur_evnt, 2)) {
case 1:
update_desc(&re->mesg);
- io_set_modified();
break;
case 2:
- update_rept(&re->rpt, re->day, &re->exc);
- io_set_modified();
+ update_rept(re->day, -1, &re->rpt, &re->exc, ADVANCED);
break;
default:
return;
@@ -503,7 +936,6 @@ void ui_day_item_edit(void)
case EVNT:
e = p->item.ev;
update_desc(&e->mesg);
- io_set_modified();
break;
case RECUR_APPT:
ra = p->item.rapt;
@@ -518,29 +950,25 @@ void ui_day_item_edit(void)
(_("Edit: "), choice_recur_appt, 5)) {
case 1:
need_check_notify = 1;
- update_start_time(&ra->start, &ra->dur, ra->dur == 0);
- io_set_modified();
+ update_start_time(&ra->start, &ra->dur, ra->rpt, ra->dur == 0);
break;
case 2:
update_duration(&ra->start, &ra->dur);
- io_set_modified();
break;
case 3:
if (notify_bar())
need_check_notify =
notify_same_recur_item(ra);
update_desc(&ra->mesg);
- io_set_modified();
break;
case 4:
need_check_notify = 1;
- update_rept(&ra->rpt, ra->start, &ra->exc);
- io_set_modified();
+ update_rept(ra->start, ra->dur, &ra->rpt, &ra->exc,
+ ADVANCED);
break;
case 5:
need_check_notify = 1;
- update_start_time(&ra->start, &ra->dur, 1);
- io_set_modified();
+ update_start_time(&ra->start, &ra->dur, ra->rpt, 1);
break;
default:
return;
@@ -558,24 +986,20 @@ void ui_day_item_edit(void)
(_("Edit: "), choice_appt, 4)) {
case 1:
need_check_notify = 1;
- update_start_time(&a->start, &a->dur, a->dur == 0);
- io_set_modified();
+ update_start_time(&a->start, &a->dur, NULL, a->dur == 0);
break;
case 2:
update_duration(&a->start, &a->dur);
- io_set_modified();
break;
case 3:
if (notify_bar())
need_check_notify =
notify_same_item(a->start);
update_desc(&a->mesg);
- io_set_modified();
break;
case 4:
need_check_notify = 1;
- update_start_time(&a->start, &a->dur, 1);
- io_set_modified();
+ update_start_time(&a->start, &a->dur, NULL, 1);
break;
default:
return;
@@ -584,12 +1008,13 @@ void ui_day_item_edit(void)
default:
break;
}
-
+ io_set_modified();
ui_calendar_monthly_view_cache_set_invalid();
if (need_check_notify)
notify_check_next_app(1);
}
+#undef ADVANCED
/* Pipe an appointment or event to an external program. */
void ui_day_item_pipe(void)
@@ -851,154 +1276,69 @@ void ui_day_item_delete(unsigned reg)
*/
void ui_day_item_repeat(void)
{
- char user_input[BUFSIZ] = "";
- const char *msg_rpt_prefix = _("Enter the repetition type:");
- const char *msg_rpt_daily = _("(d)aily");
- const char *msg_rpt_weekly = _("(w)eekly");
- const char *msg_rpt_monthly = _("(m)onthly");
- const char *msg_rpt_yearly = _("(y)early");
- const char *msg_type_choice = _("[dwmy]");
- const char *mesg_freq_1 = _("Enter the repetition frequency:");
- const char *mesg_wrong_freq = _("Invalid frequency.");
- const char *mesg_until_1 = _("Enter end date or duration ('?' for input formats):");
- const char *mesg_help_1 = _("Date: %s (year or month may be omitted). Endless duration: '0'.");
- const char *mesg_help_2 = _("Duration in days: +dd. Duration in weeks and days: +??w??d.");
- const char *mesg_wrong_1 = _("Invalid date.");
- const char *mesg_wrong_2 = _("Press [ENTER] to continue.");
- const char *wrong_type_1 = _("This item is already a repeated one.");
- const char *wrong_type_2 = _("Press [ENTER] to continue.");
- const char *mesg_older = _("Invalid date: end date must come after start date (%s).");
-
- char *msg_asktype;
- asprintf(&msg_asktype, "%s %s, %s, %s, %s", msg_rpt_prefix,
- msg_rpt_daily, msg_rpt_weekly, msg_rpt_monthly,
- msg_rpt_yearly);
-
- int type = 0, freq = 0;
- int item_nb;
+ int item_nb, simple;
struct day_item *p;
- struct recur_apoint *ra;
- time_t until;
- unsigned days;
+ long dur;
+ struct rpt rpt, *r;
+ const char *already = _("Already repeated.");
+ const char *cont = _("Press any key to continue.");
+ const char *repetition = _("A (s)imple or (a)dvanced repetition?");
+ const char *sa = _("[sa]");
if (day_item_count(0) <= 0)
- goto cleanup;
+ return;
item_nb = listbox_get_sel(&lb_apt);
p = day_get_item(item_nb);
if (p->type != APPT && p->type != EVNT) {
- status_mesg(wrong_type_1, wrong_type_2);
+ status_mesg(already, cont);
keys_wait_for_any_key(win[KEY].p);
- goto cleanup;
+ return;
}
- switch (status_ask_choice(msg_asktype, msg_type_choice, 4)) {
+ switch (status_ask_choice(repetition, sa, 2)) {
case 1:
- type = RECUR_DAILY;
+ simple = 1;
break;
case 2:
- type = RECUR_WEEKLY;
- break;
- case 3:
- type = RECUR_MONTHLY;
- break;
- case 4:
- type = RECUR_YEARLY;
+ simple = 0;
break;
default:
- goto cleanup;
- }
-
- while (freq == 0) {
- status_mesg(mesg_freq_1, "");
- if (getstring(win[STA].p, user_input, BUFSIZ, 0, 1) !=
- GETSTRING_VALID)
- goto cleanup;
- freq = atoi(user_input);
- if (freq == 0) {
- status_mesg(mesg_wrong_freq, wrong_type_2);
- keys_wait_for_any_key(win[KEY].p);
- }
- user_input[0] = '\0';
+ return;
}
- char *outstr, *datestr;
- for (;;) {
- status_mesg(mesg_until_1, "");
- if (getstring(win[STA].p, user_input, BUFSIZ, 0, 1) == GETSTRING_ESC)
- goto cleanup;
- if (strcmp(user_input, "") == 0 || strcmp(user_input, "0") == 0) {
- until = 0;
- break;
- }
- if (*user_input == '?') {
- user_input[0] = '\0';
- asprintf(&outstr, mesg_help_1, DATEFMT_DESC(conf.input_datefmt));
- status_mesg(outstr, mesg_help_2);
- mem_free(outstr);
- wgetch(win[KEY].p);
- continue;
- }
- if (*user_input == '+') {
- if (!parse_date_duration(user_input + 1, &days, p->start)) {
- status_mesg(mesg_wrong_1, mesg_wrong_2);
- keys_wgetch(win[KEY].p);
- continue;
- }
- /* Until is midnight of the day. */
- until = date_sec_change(
- update_time_in_date(p->start, 0, 0),
- 0, days
- );
- } else {
- int year, month, day;
- if (!parse_date(user_input, conf.input_datefmt,
- &year, &month, &day, ui_calendar_get_slctd_day())) {
- status_mesg(mesg_wrong_1, mesg_wrong_2);
- keys_wgetch(win[KEY].p);
- continue;
- }
- struct date d = { day, month, year };
- until = date2sec(d, 0, 0);
- }
- /* Compare days (midnights) - until-day may equal start day. */
- if (until >= get_slctd_day())
- break;
-
- datestr = date_sec2date_str(p->start, DATEFMT(conf.input_datefmt));
- asprintf(&outstr, mesg_older, datestr);
- status_mesg(outstr, wrong_type_2);
- mem_free(datestr);
- mem_free(outstr);
- keys_wgetch(win[KEY].p);
- }
+ if (p->type == APPT)
+ dur = p->item.apt->dur;
+ else
+ dur = -1;
+ rpt.type = -1;
+ rpt.freq = 1;
+ rpt.until = 0;
+ LLIST_INIT(&rpt.bymonth);
+ LLIST_INIT(&rpt.bywday);
+ LLIST_INIT(&rpt.bymonthday);
+ LLIST_INIT(&rpt.exc);
+ r = &rpt;
+ if (!update_rept(p->start, dur, &r, &rpt.exc, simple))
+ return;
- /* Set the selected APP item. */
struct day_item d = empty_day;
if (p->type == EVNT) {
struct event *ev = p->item.ev;
d.item.rev = recur_event_new(ev->mesg, ev->note, ev->day,
- ev->id, type, freq, until, NULL);
- } else if (p->type == APPT) {
+ ev->id, &rpt);
+ } else {
struct apoint *apt = p->item.apt;
- d.item.rapt = ra = recur_apoint_new(apt->mesg, apt->note,
+ d.item.rapt = recur_apoint_new(apt->mesg, apt->note,
apt->start, apt->dur,
- apt->state, type, freq,
- until, NULL);
+ apt->state, &rpt);
if (notify_bar())
- notify_check_repeated(ra);
- } else {
- EXIT(_("wrong item type"));
- /* NOTREACHED */
+ notify_check_repeated(d.item.rapt);
}
- day_set_sel_data(&d);
ui_day_item_cut(REG_BLACK_HOLE);
+ day_set_sel_data(&d);
io_set_modified();
-
ui_calendar_monthly_view_cache_set_invalid();
-
-cleanup:
- mem_free(msg_asktype);
}
/* Delete an item and save it in a register. */
diff --git a/src/utils.c b/src/utils.c
index c19c800..5322db1 100644
--- a/src/utils.c
+++ b/src/utils.c
@@ -2009,3 +2009,61 @@ long overflow_mul(long x, long y, long *z)
*z = x * y;
return 0;
}
+
+/*
+ * Return the upcoming weekday from day (possibly day itself).
+ */
+time_t next_wday(time_t day, int weekday)
+{
+ struct tm tm;
+
+ localtime_r(&day, &tm);
+ return date_sec_change(
+ day, 0, (weekday - tm.tm_wday + WEEKINDAYS) % WEEKINDAYS
+ );
+
+}
+
+/*
+ * Return the number of weekdays of the year.
+ */
+int wday_per_year(int year, int weekday)
+{
+ struct tm y_end;
+ struct date day;
+ int last_wday;
+
+ /* Find weekday and yearday of the last day of the year. */
+ day.dd = 31;
+ day.mm = 12;
+ day.yyyy = year;
+ y_end = date2tm(day, 0, 0);
+ mktime(&y_end);
+
+ /* Find date of the last weekday of the year. */
+ last_wday = (y_end.tm_yday + 1) - (y_end.tm_wday - weekday + 7) % 7;
+
+ return last_wday / 7 + (last_wday % 7 > 0);
+}
+
+/*
+ * Return the number of weekdays in month of year.
+ */
+int wday_per_month(int month, int year, int weekday)
+{
+ struct tm m_end;
+ struct date day;
+ int last_wday, m_days = days[month - 1] + (month == 2 && ISLEAP(year) ? 1 : 0);
+
+ /* Find weekday of the last day of the month. */
+ day.dd = m_days;
+ day.mm = month;
+ day.yyyy = year;
+ m_end = date2tm(day, 0, 0);
+ mktime(&m_end);
+
+ /* Find date of the last weekday of the month. */
+ last_wday = m_days - (m_end.tm_wday - weekday + 7) % 7;
+
+ return last_wday / 7 + (last_wday % 7 > 0);
+}
diff --git a/test/Makefile.am b/test/Makefile.am
index 6b04d86..b910217 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -59,6 +59,7 @@ TESTS = \
ical-009.sh \
ical-010.sh \
ical-011.sh \
+ ical-012.sh \
next-001.sh \
next-002.sh \
next-003.sh \
@@ -72,7 +73,9 @@ TESTS = \
recur-005.sh \
recur-006.sh \
recur-007.sh \
- recur-008.sh
+ recur-008.sh \
+ recur-009.sh \
+ recur-010.sh
TESTS_ENVIRONMENT = \
TEST_INIT='$(top_srcdir)/test/test-init.sh' \
@@ -134,5 +137,7 @@ EXTRA_DIST = \
data/ical-007.ical \
data/ical-008.ical \
data/ical-009.ical \
+ data/ical-012.ical \
+ data/rfc5545 \
data/todo \
data/todo-export
diff --git a/test/data/ical-009.ical b/test/data/ical-009.ical
index 73e9037..1828417 100644
--- a/test/data/ical-009.ical
+++ b/test/data/ical-009.ical
@@ -63,6 +63,54 @@ BEGIN:VTODO
PRIORITY:1
SUMMARY:an unescaped comma: ,
END:VTODO
+BEGIN:VEVENT
+DTSTART:20200406T221300
+DURATION:PT0H15M0S
+SUMMARY:Invalid STATUS
+STATUS:confirmed
+END:VEVENT
+BEGIN:VEVENT
+DTSTART:20200406T221300
+DURATION:PT0H15M0S
+SUMMARY:LOCATION twice
+LOCATION:first
+LOCATION:second
+END:VEVENT
+BEGIN:VEVENT
+DTSTART;VALUE=DATE:20200406
+DURATION:PT0H15M0S
+SUMMARY:Invalid duration (must be days or weeks)
+END:VEVENT
+BEGIN:VEVENT
+DTSTART:20200406
+DURATION:P1D
+SUMMARY:Invalid DTSTART value type
+END:VEVENT
+BEGIN:VEVENT
+DTSTART;VALUE=DATE:20200406
+SUMMARY:Invalid DTEND value type
+DTEND:20200407
+END:VEVENT
+BEGIN:VEVENT
+DTSTART;VALUE=DATE:20200406
+DURATION:P1D
+RRULE:FREQ=MONTHLY;UNTIL=20201030T120000Z
+SUMMARY:Invalid UNTIL value
+END:VEVENT
+BEGIN:VEVENT
+DTSTART;VALUE=DATE:20200406
+DURATION:P1D
+RRULE:FREQ=MONTHLY;UNTIL=20201030
+EXDATE:20200606
+SUMMARY:Invalid EXDATE value type
+END:VEVENT
+BEGIN:VEVENT
+DTSTART;VALUE=DATE:20200406
+DURATION:P1D
+RRULE:FREQ=MONTHLY;UNTIL=20201030
+EXDATE;VALUE=DATE:20200606T120000Z
+SUMMARY:Invalid EXDATE value
+END:VEVENT
BEGIN:VTODO
SUMMARY:finally\, missing end of item
END:VCALENDAR
diff --git a/test/data/ical-012.ical b/test/data/ical-012.ical
new file mode 100644
index 0000000..09385fb
--- /dev/null
+++ b/test/data/ical-012.ical
@@ -0,0 +1,93 @@
+BEGIN:VCALENDAR
+VERSION:2.0
+
+BEGIN:VEVENT
+DTSTART:20200404T204500
+DURATION:PT1H30M0S
+SUMMARY:event with one-line description
+DESCRIPTION:event with one-line description
+END:VEVENT
+
+BEGIN:VEVENT
+DTSTART:20200404T204500
+DURATION:PT1H30M0S
+SUMMARY:description and location
+DESCRIPTION:event with description\nand location
+LOCATION: Right here
+END:VEVENT
+
+BEGIN:VEVENT
+DTSTART:20200404T084100
+DURATION:PT1H30M0S
+SUMMARY:No description. Comment and status
+COMMENT:Event without description: a comment\nstreching over\nthree lines
+STATUS:CONFIRMED
+END:VEVENT
+
+BEGIN:VEVENT
+DTSTART:20200404T084100
+DURATION:PT1H30M0S
+SUMMARY:Empty description
+DESCRIPTION:
+END:VEVENT
+
+BEGIN:VEVENT
+DTSTART:20200404T084100
+DURATION:PT1H30M0S
+SUMMARY:Empty description\, but comment
+DESCRIPTION:
+COMMENT:event with empty description
+END:VEVENT
+
+BEGIN:VEVENT
+DTSTART:20200404T204500
+DURATION:PT1H30M0S
+SUMMARY:description\, status\, comment and location
+DESCRIPTION:event with\ndescription\nstatus\ncomment\nand location
+LOCATION: Right here
+COMMENT:just a repetition of description:\nevent with\ndescription\nstatus\ncomment\nand location
+STATUS:CANCELLED
+END:VEVENT
+
+BEGIN:VTODO
+PRIORITY:2
+SUMMARY:todo with one-line description
+DESCRIPTION:todo with one-line description
+END:VTODO
+
+BEGIN:VTODO
+PRIORITY:3
+SUMMARY:description and location
+DESCRIPTION:todo with description\nand location
+LOCATION: Right here
+END:VTODO
+
+BEGIN:VTODO
+PRIORITY:4
+SUMMARY:Comment and status
+COMMENT:Todo with out description. A comment\nstreching over\nthree lines
+STATUS:NEEDS-ACTION
+END:VTODO
+
+BEGIN:VTODO
+PRIORITY:5
+SUMMARY:Empty description
+DESCRIPTION:
+END:VTODO
+
+BEGIN:VTODO
+PRIORITY:6
+SUMMARY:Empty description\,but status
+DESCRIPTION:
+STATUS:COMPLETED
+END:VTODO
+
+BEGIN:VTODO
+SUMMARY:todo with description\, status\, comment and location
+DESCRIPTION:todo with\ndescription\nstatus\ncomment\nand location\,\nbut no priority
+LOCATION: Right here
+COMMENT:mostly a repetition of description:\ntodo with\ndescription\nstatus\ncomment\nand location
+STATUS:IN-PROCESS
+END:VTODO
+
+END:VCALENDAR
diff --git a/test/data/rfc5545 b/test/data/rfc5545
new file mode 100644
index 0000000..d9863ce
--- /dev/null
+++ b/test/data/rfc5545
@@ -0,0 +1,28 @@
+01/05/1997 @ 08:30 -> 01/05/1997 @ 08:30 {2Y w0 m1} |page 45: every sunday in January at 8:30 AM, every other year (FREQ=YEARLY;INTERVAL=2;BYMONTH=1;BYDAY=SU)
+01/01/1998 @ 09:00 -> 01/01/1998 @ 09:00 {1Y -> 01/31/2000 w0 w1 w2 w3 w4 w5 w6 m1} |page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+01/01/1998 @ 09:00 -> 01/01/1998 @ 09:00 {1D -> 01/31/2000 m1} |page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+09/02/1997 @ 09:00 -> 09/02/1997 @ 09:00 {1W -> 10/02/1997 w2 w4} |page 125(1): Weekly on Tuesday and Thursday for five weeks (FREQ=WEEKLY;UNTIL=19971002T000000Z;BYDAY=TU,TH)
+09/01/1997 @ 09:00 -> 09/01/1997 @ 09:00 {2W -> 12/24/1997 w1 w3 w5} |page 125: Every other week on Monday, Wednesday, and Friday until December 24, 1997, starting on Monday, September 1, 1997 (FREQ=WEEKLY;INTERVAL=2;UNTIL=19971224T000000Z;BYDAY=MO,WE,FR)
+09/05/1997 @ 09:00 -> 09/05/1997 @ 09:00 {1M -> 06/05/1998 w12} |page 126: Monthly on the first Friday for 10 occurrences (FREQ=MONTHLY;COUNT=10;BYDAY=1FR)
+09/07/1997 @ 09:00 -> 09/07/1997 @ 09:00 {2M -> 05/31/1998 w7 w-7} |page 126: Every other month on the first and last Sunday of the month for 10 occurrences (RRULE:FREQ=MONTHLY;INTERVAL=2;COUNT=10;BYDAY=1SU,-1SU)
+09/22/1997 @ 09:00 -> 09/22/1997 @ 09:00 {1M -> 02/28/1998 w-15} |page 126: Monthly on the second-to-last Monday of the month for 6 months (RRULE:FREQ=MONTHLY;COUNT=6;BYDAY=-2MO)
+09/28/1997 [1] {1M d-3} page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+09/02/1997 @ 09:00 -> 09/02/1997 @ 09:00 {1M -> 02/01/1998 d2 d15} |Page 127: Monthly on the 2nd and 15th of month for 10 occurrences (RRULE:FREQ=MONTHLY;COUNT=10;BYMONTHDAY=2,15)
+09/30/1997 @ 09:00 -> 09/30/1997 @ 09:00 {1M -> 02/01/1998 d1 d-1} |page 127: Monthly on the first and last day of the month for 10 occurrences (RRULE:FREQ=MONTHLY;COUNT=10;BYMONTHDAY=1,-1)
+09/10/1997 @ 09:00 -> 09/10/1997 @ 09:00 {18M -> 03/13/1999 d10 d11 d12 d13 d14 d15} |page 127: Every 18 months on the 10th thru 15th of the month for 10 occurrences (RRULE:FREQ=MONTHLY;INTERVAL=18;COUNT=10;BYMONTHDAY=10,11,12,13,14,15)
+09/02/1997 @ 09:00 -> 09/02/1997 @ 09:00 {2M w2} |page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+06/10/1997 @ 09:00 -> 06/10/1997 @ 09:00 {1Y -> 07/10/2001 m6 m7} |page 128: Yearly in June and July for 10 occurrences (RRULE:FREQ=YEARLY;COUNT=10;BYMONTH=6,7)
+03/10/1997 @ 09:00 -> 03/10/1997 @ 09:00 {2Y -> 03/10/2003 m1 m2 m3} |page 128: Every other year in January, February and March for 10 occurrences (RRULE:FREQ=YEARLY;INTERVAL=2;COUNT=10;BYMONTH=1,2,3)
+05/19/1997 [1] {1Y w141} page 128: Every 20th Monday of the year, forever (RRULE:FREQ=YEARLY;BYDAY=20MO)
+03/13/1997 @ 09:00 -> 03/13/1997 @ 09:00 {1Y w4 m3} |page 129: Every Thursday in March, forever (RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=TH)
+06/05/1997 @ 09:00 -> 06/05/1997 @ 09:00 {1Y w4 m6 m7 m8} |page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+02/13/1998 [1] {1M d13 w5} page 129: Every Friday the 13th, forever (RRULE:FREQ=MONTHLY;BYDAY=FR;BYMONTHDAY=13)
+09/13/1997 [1] {1M d7 d8 d9 d10 d11 d12 d13 w6} page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+11/05/1996 [1] {4Y d2 d3 d4 d5 d6 d7 d8 w2 m11} page 130: Every 4 years, the first Tuesday after a Monday in November, forever (U.S. Presidential Election day) (RRULE:FREQ=YEARLY;INTERVAL=4;BYMONTH=11;BYDAY=TU;BYMONTHDAY=2,3,4,5,6,7,8)
+08/05/1997 @ 09:00 -> 08/05/1997 @ 09:00 {2W -> 08/31/1997 w0 w2} |page 131: An example where the days generated makes a difference because of weekstart (RRULE:FREQ=WEEKLY;INTERVAL=2;COUNT=4;BYDAY=TU,SU)
+01/15/2007 [1] {1M -> 03/30/2007 d15 d30} page 132: An example where an invalid date (i.e. February 30) is ignored (RRULE:FREQ=MONTHLY;BYMONTHDAY=15,30;COUNT=5)
+03/30/1997 @ 09:00 -> 03/30/1997 @ 09:00 {1Y w-7 m3} |Last Sunday in March, forever (RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU)
+12/25/1997 [1] {3Y w-11} Last Thursday of the year every third year, forever (FREQ=YEARLY;INTERVAL=3;BYDAY=-1TH)
+06/22/1997 [1] {2Y w0 w1} Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+02/01/1997 [1] {1Y -> 01/31/2005 d1 d29 m2} Every year on February 1 and 29 for eight years (RRULE:FREQ=YEARLY;UNTIL=20050131T000000Z;BYMONTH=2;BYMONTHDAY=1,29)
+08/01/2020 @ 08:41 -> 08/01/2020 @ 10:11 {1M w-41} |negative ordered weekday may not exist
diff --git a/test/ical-009.sh b/test/ical-009.sh
index 9558f15..c8c1c9c 100755
--- a/test/ical-009.sh
+++ b/test/ical-009.sh
@@ -7,26 +7,37 @@ if [ "$1" = 'actual' ]; then
mkdir .calcurse || exit 1
cp "$DATA_DIR/conf" .calcurse || exit 1
out=$("$CALCURSE" -D "$PWD/.calcurse" -i "$DATA_DIR/ical-009.ical" 2>&1)
- echo "$out" | sed -n '4,5p'
- log=$(echo "$out" | awk '$1 == "See" {print $2}')
- cat "$log" | sed '1,17d'
+ # Print the import report (stdout).
+ echo "$out" | awk '$1 == "Import"; $2 == "apps"'
+ # Find the log file and print the log messages (stderr).
+ logfile=$(echo "$out" | awk '$1 == "See" { print $2 }')
+ sed '1,18d' "$logfile"
+ # One empty note file.
+ cat "$PWD/.calcurse/notes"/* | wc | awk '{ print $1 $2 $3 }'
rm -rf .calcurse || exit 1
elif [ "$1" = 'expected' ]; then
cat <<EOD
-Import process report: 0068 lines read
-1 app / 0 events / 1 todo / 11 skipped
-
-VEVENT [12]: could not retrieve event start time.
+Import process report: 0116 lines read
+2 apps / 0 events / 1 todo / 18 skipped
+VEVENT [12]: invalid or malformed event start time.
VEVENT [17]: recurrence frequency not recognized.
-VEVENT [23]: malformed summary line
+VEVENT [23]: malformed summary line.
VTODO [28]: item priority is invalid (must be between 0 and 9).
VEVENT [32]: malformed exceptions line.
VEVENT [39]: line break in summary.
VEVENT [44]: malformed description line.
VEVENT [50]: malformed description.
-VEVENT [56]: empty description.
VTODO [62]: malformed summary.
-VTODO [66]: The ical file seems to be malformed. The end of item was not found.
+VEVENT [66]: invalid status value.
+VEVENT [72]: only one location allowed.
+VEVENT [79]: invalid duration.
+VEVENT [84]: invalid or malformed event start time.
+VEVENT [89]: invalid end time value type.
+VEVENT [94]: invalid until format.
+VEVENT [100]: invalid exception date value type.
+VEVENT [107]: invalid exception.
+VTODO [114]: The ical file seems to be malformed. The end of item was not found.
+101
EOD
else
./run-test "$0"
diff --git a/test/ical-012.sh b/test/ical-012.sh
new file mode 100755
index 0000000..9175db9
--- /dev/null
+++ b/test/ical-012.sh
@@ -0,0 +1,76 @@
+#!/bin/sh
+# Note file creation. Eleven note files are created for 6 apps and 6 todos.
+# To produce a fixed, predictable directory listing it is necessary that the
+# notes are of different sizes (except for the vevent and vtodo empty note which
+# is shared).
+
+. "${TEST_INIT:-./test-init.sh}"
+
+if [ "$1" = 'actual' ]; then
+ mkdir .calcurse &&
+ cp "$DATA_DIR/conf" .calcurse || exit 1
+ "$CALCURSE" -D "$PWD/.calcurse" -i "$DATA_DIR/ical-012.ical"
+ (cd "$PWD/.calcurse/notes/"; cat $(ls -S1))
+ rm -rf .calcurse || exit 1
+elif [ "$1" = 'expected' ]; then
+ cat <<EOD
+Import process report: 0093 lines read
+6 apps / 0 events / 6 todos / 0 skipped
+todo with
+description
+status
+comment
+and location,
+but no priority
+--
+Location: Right here
+Comment: mostly a repetition of description:
+ todo with
+ description
+ status
+ comment
+ and location
+Status: IN-PROCESS
+event with
+description
+status
+comment
+and location
+--
+Location: Right here
+Comment: just a repetition of description:
+ event with
+ description
+ status
+ comment
+ and location
+Status: CANCELLED
+Comment: Todo with out description. A comment
+ streching over
+ three lines
+Status: NEEDS-ACTION
+Comment: Event without description: a comment
+ streching over
+ three lines
+Status: CONFIRMED
+event with description
+and location
+--
+Location: Right here
+todo with description
+and location
+--
+Location: Right here
+
+--
+Comment: event with empty description
+event with one-line description
+todo with one-line description
+
+--
+Status: COMPLETED
+
+EOD
+else
+ ./run-test "$0"
+fi
diff --git a/test/recur-009.sh b/test/recur-009.sh
new file mode 100755
index 0000000..2558b4c
--- /dev/null
+++ b/test/recur-009.sh
@@ -0,0 +1,5342 @@
+#!/bin/sh
+# Support of selected RFC5545 recurrence rules.
+
+. "${TEST_INIT:-./test-init.sh}"
+
+if [ "$1" = 'actual' ]; then
+ "$CALCURSE" --read-only -D "$DATA_DIR"/ -c "$DATA_DIR/rfc5545" \
+ -Q --from 1/1/1996 --to 12/31/2007 --filter-type recur
+ echo ""
+ echo "Floating point exception?"
+ "$CALCURSE" --read-only -D "$DATA_DIR"/ -c "$DATA_DIR/rfc5545" \
+ -Q --day 8/1/2020 --filter-type recur &&
+ "$CALCURSE" --read-only -D "$DATA_DIR"/ -c "$DATA_DIR/rfc5545" \
+ -Q --day 11/1/2020 --filter-type recur &&
+ echo "No Floating point exception on November 1, 2020"
+elif [ "$1" = 'expected' ]; then
+ cat <<EOD
+11/05/96:
+ * page 130: Every 4 years, the first Tuesday after a Monday in November, forever (U.S. Presidential Election day) (RRULE:FREQ=YEARLY;INTERVAL=4;BYMONTH=11;BYDAY=TU;BYMONTHDAY=2,3,4,5,6,7,8)
+
+01/05/97:
+ - 08:30 -> 08:30
+ page 45: every sunday in January at 8:30 AM, every other year (FREQ=YEARLY;INTERVAL=2;BYMONTH=1;BYDAY=SU)
+
+01/12/97:
+ - 08:30 -> 08:30
+ page 45: every sunday in January at 8:30 AM, every other year (FREQ=YEARLY;INTERVAL=2;BYMONTH=1;BYDAY=SU)
+
+01/19/97:
+ - 08:30 -> 08:30
+ page 45: every sunday in January at 8:30 AM, every other year (FREQ=YEARLY;INTERVAL=2;BYMONTH=1;BYDAY=SU)
+
+01/26/97:
+ - 08:30 -> 08:30
+ page 45: every sunday in January at 8:30 AM, every other year (FREQ=YEARLY;INTERVAL=2;BYMONTH=1;BYDAY=SU)
+
+02/01/97:
+ * Every year on February 1 and 29 for eight years (RRULE:FREQ=YEARLY;UNTIL=20050131T000000Z;BYMONTH=2;BYMONTHDAY=1,29)
+
+03/10/97:
+ - 09:00 -> 09:00
+ page 128: Every other year in January, February and March for 10 occurrences (RRULE:FREQ=YEARLY;INTERVAL=2;COUNT=10;BYMONTH=1,2,3)
+
+03/13/97:
+ - 09:00 -> 09:00
+ page 129: Every Thursday in March, forever (RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=TH)
+
+03/20/97:
+ - 09:00 -> 09:00
+ page 129: Every Thursday in March, forever (RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=TH)
+
+03/27/97:
+ - 09:00 -> 09:00
+ page 129: Every Thursday in March, forever (RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=TH)
+
+03/30/97:
+ - 09:00 -> 09:00
+ Last Sunday in March, forever (RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU)
+
+05/19/97:
+ * page 128: Every 20th Monday of the year, forever (RRULE:FREQ=YEARLY;BYDAY=20MO)
+
+06/05/97:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+06/10/97:
+ - 09:00 -> 09:00
+ page 128: Yearly in June and July for 10 occurrences (RRULE:FREQ=YEARLY;COUNT=10;BYMONTH=6,7)
+
+06/12/97:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+06/19/97:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+06/22/97:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+06/23/97:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+06/26/97:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+06/29/97:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+06/30/97:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+07/03/97:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+07/06/97:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+07/07/97:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+07/10/97:
+ - 09:00 -> 09:00
+ page 128: Yearly in June and July for 10 occurrences (RRULE:FREQ=YEARLY;COUNT=10;BYMONTH=6,7)
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+07/13/97:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+07/14/97:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+07/17/97:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+07/20/97:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+07/21/97:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+07/24/97:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+07/27/97:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+07/28/97:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+07/31/97:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+08/03/97:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+08/04/97:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+08/05/97:
+ - 09:00 -> 09:00
+ page 131: An example where the days generated makes a difference because of weekstart (RRULE:FREQ=WEEKLY;INTERVAL=2;COUNT=4;BYDAY=TU,SU)
+
+08/07/97:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+08/10/97:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+ - 09:00 -> 09:00
+ page 131: An example where the days generated makes a difference because of weekstart (RRULE:FREQ=WEEKLY;INTERVAL=2;COUNT=4;BYDAY=TU,SU)
+
+08/11/97:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+08/14/97:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+08/17/97:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+08/18/97:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+08/19/97:
+ - 09:00 -> 09:00
+ page 131: An example where the days generated makes a difference because of weekstart (RRULE:FREQ=WEEKLY;INTERVAL=2;COUNT=4;BYDAY=TU,SU)
+
+08/21/97:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+08/24/97:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+ - 09:00 -> 09:00
+ page 131: An example where the days generated makes a difference because of weekstart (RRULE:FREQ=WEEKLY;INTERVAL=2;COUNT=4;BYDAY=TU,SU)
+
+08/25/97:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+08/28/97:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+08/31/97:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+09/01/97:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+ - 09:00 -> 09:00
+ page 125: Every other week on Monday, Wednesday, and Friday until December 24, 1997, starting on Monday, September 1, 1997 (FREQ=WEEKLY;INTERVAL=2;UNTIL=19971224T000000Z;BYDAY=MO,WE,FR)
+
+09/02/97:
+ - 09:00 -> 09:00
+ Page 127: Monthly on the 2nd and 15th of month for 10 occurrences (RRULE:FREQ=MONTHLY;COUNT=10;BYMONTHDAY=2,15)
+ - 09:00 -> 09:00
+ page 125(1): Weekly on Tuesday and Thursday for five weeks (FREQ=WEEKLY;UNTIL=19971002T000000Z;BYDAY=TU,TH)
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+09/03/97:
+ - 09:00 -> 09:00
+ page 125: Every other week on Monday, Wednesday, and Friday until December 24, 1997, starting on Monday, September 1, 1997 (FREQ=WEEKLY;INTERVAL=2;UNTIL=19971224T000000Z;BYDAY=MO,WE,FR)
+
+09/04/97:
+ - 09:00 -> 09:00
+ page 125(1): Weekly on Tuesday and Thursday for five weeks (FREQ=WEEKLY;UNTIL=19971002T000000Z;BYDAY=TU,TH)
+
+09/05/97:
+ - 09:00 -> 09:00
+ page 125: Every other week on Monday, Wednesday, and Friday until December 24, 1997, starting on Monday, September 1, 1997 (FREQ=WEEKLY;INTERVAL=2;UNTIL=19971224T000000Z;BYDAY=MO,WE,FR)
+ - 09:00 -> 09:00
+ page 126: Monthly on the first Friday for 10 occurrences (FREQ=MONTHLY;COUNT=10;BYDAY=1FR)
+
+09/07/97:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+ - 09:00 -> 09:00
+ page 126: Every other month on the first and last Sunday of the month for 10 occurrences (RRULE:FREQ=MONTHLY;INTERVAL=2;COUNT=10;BYDAY=1SU,-1SU)
+
+09/08/97:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+09/09/97:
+ - 09:00 -> 09:00
+ page 125(1): Weekly on Tuesday and Thursday for five weeks (FREQ=WEEKLY;UNTIL=19971002T000000Z;BYDAY=TU,TH)
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+09/10/97:
+ - 09:00 -> 09:00
+ page 127: Every 18 months on the 10th thru 15th of the month for 10 occurrences (RRULE:FREQ=MONTHLY;INTERVAL=18;COUNT=10;BYMONTHDAY=10,11,12,13,14,15)
+
+09/11/97:
+ - 09:00 -> 09:00
+ page 125(1): Weekly on Tuesday and Thursday for five weeks (FREQ=WEEKLY;UNTIL=19971002T000000Z;BYDAY=TU,TH)
+ - 09:00 -> 09:00
+ page 127: Every 18 months on the 10th thru 15th of the month for 10 occurrences (RRULE:FREQ=MONTHLY;INTERVAL=18;COUNT=10;BYMONTHDAY=10,11,12,13,14,15)
+
+09/12/97:
+ - 09:00 -> 09:00
+ page 127: Every 18 months on the 10th thru 15th of the month for 10 occurrences (RRULE:FREQ=MONTHLY;INTERVAL=18;COUNT=10;BYMONTHDAY=10,11,12,13,14,15)
+
+09/13/97:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+ - 09:00 -> 09:00
+ page 127: Every 18 months on the 10th thru 15th of the month for 10 occurrences (RRULE:FREQ=MONTHLY;INTERVAL=18;COUNT=10;BYMONTHDAY=10,11,12,13,14,15)
+
+09/14/97:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+ - 09:00 -> 09:00
+ page 127: Every 18 months on the 10th thru 15th of the month for 10 occurrences (RRULE:FREQ=MONTHLY;INTERVAL=18;COUNT=10;BYMONTHDAY=10,11,12,13,14,15)
+
+09/15/97:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+ - 09:00 -> 09:00
+ Page 127: Monthly on the 2nd and 15th of month for 10 occurrences (RRULE:FREQ=MONTHLY;COUNT=10;BYMONTHDAY=2,15)
+ - 09:00 -> 09:00
+ page 125: Every other week on Monday, Wednesday, and Friday until December 24, 1997, starting on Monday, September 1, 1997 (FREQ=WEEKLY;INTERVAL=2;UNTIL=19971224T000000Z;BYDAY=MO,WE,FR)
+ - 09:00 -> 09:00
+ page 127: Every 18 months on the 10th thru 15th of the month for 10 occurrences (RRULE:FREQ=MONTHLY;INTERVAL=18;COUNT=10;BYMONTHDAY=10,11,12,13,14,15)
+
+09/16/97:
+ - 09:00 -> 09:00
+ page 125(1): Weekly on Tuesday and Thursday for five weeks (FREQ=WEEKLY;UNTIL=19971002T000000Z;BYDAY=TU,TH)
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+09/17/97:
+ - 09:00 -> 09:00
+ page 125: Every other week on Monday, Wednesday, and Friday until December 24, 1997, starting on Monday, September 1, 1997 (FREQ=WEEKLY;INTERVAL=2;UNTIL=19971224T000000Z;BYDAY=MO,WE,FR)
+
+09/18/97:
+ - 09:00 -> 09:00
+ page 125(1): Weekly on Tuesday and Thursday for five weeks (FREQ=WEEKLY;UNTIL=19971002T000000Z;BYDAY=TU,TH)
+
+09/19/97:
+ - 09:00 -> 09:00
+ page 125: Every other week on Monday, Wednesday, and Friday until December 24, 1997, starting on Monday, September 1, 1997 (FREQ=WEEKLY;INTERVAL=2;UNTIL=19971224T000000Z;BYDAY=MO,WE,FR)
+
+09/21/97:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+09/22/97:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+ - 09:00 -> 09:00
+ page 126: Monthly on the second-to-last Monday of the month for 6 months (RRULE:FREQ=MONTHLY;COUNT=6;BYDAY=-2MO)
+
+09/23/97:
+ - 09:00 -> 09:00
+ page 125(1): Weekly on Tuesday and Thursday for five weeks (FREQ=WEEKLY;UNTIL=19971002T000000Z;BYDAY=TU,TH)
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+09/25/97:
+ - 09:00 -> 09:00
+ page 125(1): Weekly on Tuesday and Thursday for five weeks (FREQ=WEEKLY;UNTIL=19971002T000000Z;BYDAY=TU,TH)
+
+09/28/97:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+ - 09:00 -> 09:00
+ page 126: Every other month on the first and last Sunday of the month for 10 occurrences (RRULE:FREQ=MONTHLY;INTERVAL=2;COUNT=10;BYDAY=1SU,-1SU)
+
+09/29/97:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+ - 09:00 -> 09:00
+ page 125: Every other week on Monday, Wednesday, and Friday until December 24, 1997, starting on Monday, September 1, 1997 (FREQ=WEEKLY;INTERVAL=2;UNTIL=19971224T000000Z;BYDAY=MO,WE,FR)
+
+09/30/97:
+ - 09:00 -> 09:00
+ page 125(1): Weekly on Tuesday and Thursday for five weeks (FREQ=WEEKLY;UNTIL=19971002T000000Z;BYDAY=TU,TH)
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+ - 09:00 -> 09:00
+ page 127: Monthly on the first and last day of the month for 10 occurrences (RRULE:FREQ=MONTHLY;COUNT=10;BYMONTHDAY=1,-1)
+
+10/01/97:
+ - 09:00 -> 09:00
+ page 125: Every other week on Monday, Wednesday, and Friday until December 24, 1997, starting on Monday, September 1, 1997 (FREQ=WEEKLY;INTERVAL=2;UNTIL=19971224T000000Z;BYDAY=MO,WE,FR)
+ - 09:00 -> 09:00
+ page 127: Monthly on the first and last day of the month for 10 occurrences (RRULE:FREQ=MONTHLY;COUNT=10;BYMONTHDAY=1,-1)
+
+10/02/97:
+ - 09:00 -> 09:00
+ Page 127: Monthly on the 2nd and 15th of month for 10 occurrences (RRULE:FREQ=MONTHLY;COUNT=10;BYMONTHDAY=2,15)
+ - 09:00 -> 09:00
+ page 125(1): Weekly on Tuesday and Thursday for five weeks (FREQ=WEEKLY;UNTIL=19971002T000000Z;BYDAY=TU,TH)
+
+10/03/97:
+ - 09:00 -> 09:00
+ page 125: Every other week on Monday, Wednesday, and Friday until December 24, 1997, starting on Monday, September 1, 1997 (FREQ=WEEKLY;INTERVAL=2;UNTIL=19971224T000000Z;BYDAY=MO,WE,FR)
+ - 09:00 -> 09:00
+ page 126: Monthly on the first Friday for 10 occurrences (FREQ=MONTHLY;COUNT=10;BYDAY=1FR)
+
+10/05/97:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+10/06/97:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+10/11/97:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+10/12/97:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+10/13/97:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+ - 09:00 -> 09:00
+ page 125: Every other week on Monday, Wednesday, and Friday until December 24, 1997, starting on Monday, September 1, 1997 (FREQ=WEEKLY;INTERVAL=2;UNTIL=19971224T000000Z;BYDAY=MO,WE,FR)
+
+10/15/97:
+ - 09:00 -> 09:00
+ Page 127: Monthly on the 2nd and 15th of month for 10 occurrences (RRULE:FREQ=MONTHLY;COUNT=10;BYMONTHDAY=2,15)
+ - 09:00 -> 09:00
+ page 125: Every other week on Monday, Wednesday, and Friday until December 24, 1997, starting on Monday, September 1, 1997 (FREQ=WEEKLY;INTERVAL=2;UNTIL=19971224T000000Z;BYDAY=MO,WE,FR)
+
+10/17/97:
+ - 09:00 -> 09:00
+ page 125: Every other week on Monday, Wednesday, and Friday until December 24, 1997, starting on Monday, September 1, 1997 (FREQ=WEEKLY;INTERVAL=2;UNTIL=19971224T000000Z;BYDAY=MO,WE,FR)
+
+10/19/97:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+10/20/97:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+ - 09:00 -> 09:00
+ page 126: Monthly on the second-to-last Monday of the month for 6 months (RRULE:FREQ=MONTHLY;COUNT=6;BYDAY=-2MO)
+
+10/26/97:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+10/27/97:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+ - 09:00 -> 09:00
+ page 125: Every other week on Monday, Wednesday, and Friday until December 24, 1997, starting on Monday, September 1, 1997 (FREQ=WEEKLY;INTERVAL=2;UNTIL=19971224T000000Z;BYDAY=MO,WE,FR)
+
+10/29/97:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+ - 09:00 -> 09:00
+ page 125: Every other week on Monday, Wednesday, and Friday until December 24, 1997, starting on Monday, September 1, 1997 (FREQ=WEEKLY;INTERVAL=2;UNTIL=19971224T000000Z;BYDAY=MO,WE,FR)
+
+10/31/97:
+ - 09:00 -> 09:00
+ page 125: Every other week on Monday, Wednesday, and Friday until December 24, 1997, starting on Monday, September 1, 1997 (FREQ=WEEKLY;INTERVAL=2;UNTIL=19971224T000000Z;BYDAY=MO,WE,FR)
+ - 09:00 -> 09:00
+ page 127: Monthly on the first and last day of the month for 10 occurrences (RRULE:FREQ=MONTHLY;COUNT=10;BYMONTHDAY=1,-1)
+
+11/01/97:
+ - 09:00 -> 09:00
+ page 127: Monthly on the first and last day of the month for 10 occurrences (RRULE:FREQ=MONTHLY;COUNT=10;BYMONTHDAY=1,-1)
+
+11/02/97:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+ - 09:00 -> 09:00
+ Page 127: Monthly on the 2nd and 15th of month for 10 occurrences (RRULE:FREQ=MONTHLY;COUNT=10;BYMONTHDAY=2,15)
+ - 09:00 -> 09:00
+ page 126: Every other month on the first and last Sunday of the month for 10 occurrences (RRULE:FREQ=MONTHLY;INTERVAL=2;COUNT=10;BYDAY=1SU,-1SU)
+
+11/03/97:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+11/04/97:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+11/07/97:
+ - 09:00 -> 09:00
+ page 126: Monthly on the first Friday for 10 occurrences (FREQ=MONTHLY;COUNT=10;BYDAY=1FR)
+
+11/08/97:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+11/09/97:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+11/10/97:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+ - 09:00 -> 09:00
+ page 125: Every other week on Monday, Wednesday, and Friday until December 24, 1997, starting on Monday, September 1, 1997 (FREQ=WEEKLY;INTERVAL=2;UNTIL=19971224T000000Z;BYDAY=MO,WE,FR)
+
+11/11/97:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+11/12/97:
+ - 09:00 -> 09:00
+ page 125: Every other week on Monday, Wednesday, and Friday until December 24, 1997, starting on Monday, September 1, 1997 (FREQ=WEEKLY;INTERVAL=2;UNTIL=19971224T000000Z;BYDAY=MO,WE,FR)
+
+11/14/97:
+ - 09:00 -> 09:00
+ page 125: Every other week on Monday, Wednesday, and Friday until December 24, 1997, starting on Monday, September 1, 1997 (FREQ=WEEKLY;INTERVAL=2;UNTIL=19971224T000000Z;BYDAY=MO,WE,FR)
+
+11/15/97:
+ - 09:00 -> 09:00
+ Page 127: Monthly on the 2nd and 15th of month for 10 occurrences (RRULE:FREQ=MONTHLY;COUNT=10;BYMONTHDAY=2,15)
+
+11/16/97:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+11/17/97:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+ - 09:00 -> 09:00
+ page 126: Monthly on the second-to-last Monday of the month for 6 months (RRULE:FREQ=MONTHLY;COUNT=6;BYDAY=-2MO)
+
+11/18/97:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+11/23/97:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+11/24/97:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+ - 09:00 -> 09:00
+ page 125: Every other week on Monday, Wednesday, and Friday until December 24, 1997, starting on Monday, September 1, 1997 (FREQ=WEEKLY;INTERVAL=2;UNTIL=19971224T000000Z;BYDAY=MO,WE,FR)
+
+11/25/97:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+11/26/97:
+ - 09:00 -> 09:00
+ page 125: Every other week on Monday, Wednesday, and Friday until December 24, 1997, starting on Monday, September 1, 1997 (FREQ=WEEKLY;INTERVAL=2;UNTIL=19971224T000000Z;BYDAY=MO,WE,FR)
+
+11/28/97:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+ - 09:00 -> 09:00
+ page 125: Every other week on Monday, Wednesday, and Friday until December 24, 1997, starting on Monday, September 1, 1997 (FREQ=WEEKLY;INTERVAL=2;UNTIL=19971224T000000Z;BYDAY=MO,WE,FR)
+
+11/30/97:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+ - 09:00 -> 09:00
+ page 126: Every other month on the first and last Sunday of the month for 10 occurrences (RRULE:FREQ=MONTHLY;INTERVAL=2;COUNT=10;BYDAY=1SU,-1SU)
+ - 09:00 -> 09:00
+ page 127: Monthly on the first and last day of the month for 10 occurrences (RRULE:FREQ=MONTHLY;COUNT=10;BYMONTHDAY=1,-1)
+
+12/01/97:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+ - 09:00 -> 09:00
+ page 127: Monthly on the first and last day of the month for 10 occurrences (RRULE:FREQ=MONTHLY;COUNT=10;BYMONTHDAY=1,-1)
+
+12/02/97:
+ - 09:00 -> 09:00
+ Page 127: Monthly on the 2nd and 15th of month for 10 occurrences (RRULE:FREQ=MONTHLY;COUNT=10;BYMONTHDAY=2,15)
+
+12/05/97:
+ - 09:00 -> 09:00
+ page 126: Monthly on the first Friday for 10 occurrences (FREQ=MONTHLY;COUNT=10;BYDAY=1FR)
+
+12/07/97:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+12/08/97:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+ - 09:00 -> 09:00
+ page 125: Every other week on Monday, Wednesday, and Friday until December 24, 1997, starting on Monday, September 1, 1997 (FREQ=WEEKLY;INTERVAL=2;UNTIL=19971224T000000Z;BYDAY=MO,WE,FR)
+
+12/10/97:
+ - 09:00 -> 09:00
+ page 125: Every other week on Monday, Wednesday, and Friday until December 24, 1997, starting on Monday, September 1, 1997 (FREQ=WEEKLY;INTERVAL=2;UNTIL=19971224T000000Z;BYDAY=MO,WE,FR)
+
+12/12/97:
+ - 09:00 -> 09:00
+ page 125: Every other week on Monday, Wednesday, and Friday until December 24, 1997, starting on Monday, September 1, 1997 (FREQ=WEEKLY;INTERVAL=2;UNTIL=19971224T000000Z;BYDAY=MO,WE,FR)
+
+12/13/97:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+12/14/97:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+12/15/97:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+ - 09:00 -> 09:00
+ Page 127: Monthly on the 2nd and 15th of month for 10 occurrences (RRULE:FREQ=MONTHLY;COUNT=10;BYMONTHDAY=2,15)
+
+12/21/97:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+12/22/97:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+ - 09:00 -> 09:00
+ page 125: Every other week on Monday, Wednesday, and Friday until December 24, 1997, starting on Monday, September 1, 1997 (FREQ=WEEKLY;INTERVAL=2;UNTIL=19971224T000000Z;BYDAY=MO,WE,FR)
+ - 09:00 -> 09:00
+ page 126: Monthly on the second-to-last Monday of the month for 6 months (RRULE:FREQ=MONTHLY;COUNT=6;BYDAY=-2MO)
+
+12/24/97:
+ - 09:00 -> 09:00
+ page 125: Every other week on Monday, Wednesday, and Friday until December 24, 1997, starting on Monday, September 1, 1997 (FREQ=WEEKLY;INTERVAL=2;UNTIL=19971224T000000Z;BYDAY=MO,WE,FR)
+
+12/25/97:
+ * Last Thursday of the year every third year, forever (FREQ=YEARLY;INTERVAL=3;BYDAY=-1TH)
+
+12/28/97:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+12/29/97:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+12/31/97:
+ - 09:00 -> 09:00
+ page 127: Monthly on the first and last day of the month for 10 occurrences (RRULE:FREQ=MONTHLY;COUNT=10;BYMONTHDAY=1,-1)
+
+01/01/98:
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+ - 09:00 -> 09:00
+ page 127: Monthly on the first and last day of the month for 10 occurrences (RRULE:FREQ=MONTHLY;COUNT=10;BYMONTHDAY=1,-1)
+
+01/02/98:
+ - 09:00 -> 09:00
+ Page 127: Monthly on the 2nd and 15th of month for 10 occurrences (RRULE:FREQ=MONTHLY;COUNT=10;BYMONTHDAY=2,15)
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+ - 09:00 -> 09:00
+ page 126: Monthly on the first Friday for 10 occurrences (FREQ=MONTHLY;COUNT=10;BYDAY=1FR)
+
+01/03/98:
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+
+01/04/98:
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+ - 09:00 -> 09:00
+ page 126: Every other month on the first and last Sunday of the month for 10 occurrences (RRULE:FREQ=MONTHLY;INTERVAL=2;COUNT=10;BYDAY=1SU,-1SU)
+
+01/05/98:
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+
+01/06/98:
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+01/07/98:
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+
+01/08/98:
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+
+01/09/98:
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+
+01/10/98:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+
+01/11/98:
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+
+01/12/98:
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+
+01/13/98:
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+01/14/98:
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+
+01/15/98:
+ - 09:00 -> 09:00
+ Page 127: Monthly on the 2nd and 15th of month for 10 occurrences (RRULE:FREQ=MONTHLY;COUNT=10;BYMONTHDAY=2,15)
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+
+01/16/98:
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+
+01/17/98:
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+
+01/18/98:
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+
+01/19/98:
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+ - 09:00 -> 09:00
+ page 126: Monthly on the second-to-last Monday of the month for 6 months (RRULE:FREQ=MONTHLY;COUNT=6;BYDAY=-2MO)
+
+01/20/98:
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+01/21/98:
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+
+01/22/98:
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+
+01/23/98:
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+
+01/24/98:
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+
+01/25/98:
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+ - 09:00 -> 09:00
+ page 126: Every other month on the first and last Sunday of the month for 10 occurrences (RRULE:FREQ=MONTHLY;INTERVAL=2;COUNT=10;BYDAY=1SU,-1SU)
+
+01/26/98:
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+
+01/27/98:
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+01/28/98:
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+
+01/29/98:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+
+01/30/98:
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+
+01/31/98:
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+ - 09:00 -> 09:00
+ page 127: Monthly on the first and last day of the month for 10 occurrences (RRULE:FREQ=MONTHLY;COUNT=10;BYMONTHDAY=1,-1)
+
+02/01/98:
+ * Every year on February 1 and 29 for eight years (RRULE:FREQ=YEARLY;UNTIL=20050131T000000Z;BYMONTH=2;BYMONTHDAY=1,29)
+ - 09:00 -> 09:00
+ page 127: Monthly on the first and last day of the month for 10 occurrences (RRULE:FREQ=MONTHLY;COUNT=10;BYMONTHDAY=1,-1)
+
+02/06/98:
+ - 09:00 -> 09:00
+ page 126: Monthly on the first Friday for 10 occurrences (FREQ=MONTHLY;COUNT=10;BYDAY=1FR)
+
+02/07/98:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+02/13/98:
+ * page 129: Every Friday the 13th, forever (RRULE:FREQ=MONTHLY;BYDAY=FR;BYMONTHDAY=13)
+
+02/16/98:
+ - 09:00 -> 09:00
+ page 126: Monthly on the second-to-last Monday of the month for 6 months (RRULE:FREQ=MONTHLY;COUNT=6;BYDAY=-2MO)
+
+02/26/98:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+03/01/98:
+ - 09:00 -> 09:00
+ page 126: Every other month on the first and last Sunday of the month for 10 occurrences (RRULE:FREQ=MONTHLY;INTERVAL=2;COUNT=10;BYDAY=1SU,-1SU)
+
+03/03/98:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+03/05/98:
+ - 09:00 -> 09:00
+ page 129: Every Thursday in March, forever (RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=TH)
+
+03/06/98:
+ - 09:00 -> 09:00
+ page 126: Monthly on the first Friday for 10 occurrences (FREQ=MONTHLY;COUNT=10;BYDAY=1FR)
+
+03/07/98:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+03/10/98:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+03/12/98:
+ - 09:00 -> 09:00
+ page 129: Every Thursday in March, forever (RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=TH)
+
+03/13/98:
+ * page 129: Every Friday the 13th, forever (RRULE:FREQ=MONTHLY;BYDAY=FR;BYMONTHDAY=13)
+
+03/17/98:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+03/19/98:
+ - 09:00 -> 09:00
+ page 129: Every Thursday in March, forever (RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=TH)
+
+03/24/98:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+03/26/98:
+ - 09:00 -> 09:00
+ page 129: Every Thursday in March, forever (RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=TH)
+
+03/29/98:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+ - 09:00 -> 09:00
+ Last Sunday in March, forever (RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU)
+ - 09:00 -> 09:00
+ page 126: Every other month on the first and last Sunday of the month for 10 occurrences (RRULE:FREQ=MONTHLY;INTERVAL=2;COUNT=10;BYDAY=1SU,-1SU)
+
+03/31/98:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+04/03/98:
+ - 09:00 -> 09:00
+ page 126: Monthly on the first Friday for 10 occurrences (FREQ=MONTHLY;COUNT=10;BYDAY=1FR)
+
+04/11/98:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+04/28/98:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+05/01/98:
+ - 09:00 -> 09:00
+ page 126: Monthly on the first Friday for 10 occurrences (FREQ=MONTHLY;COUNT=10;BYDAY=1FR)
+
+05/03/98:
+ - 09:00 -> 09:00
+ page 126: Every other month on the first and last Sunday of the month for 10 occurrences (RRULE:FREQ=MONTHLY;INTERVAL=2;COUNT=10;BYDAY=1SU,-1SU)
+
+05/05/98:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+05/09/98:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+05/12/98:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+05/18/98:
+ * page 128: Every 20th Monday of the year, forever (RRULE:FREQ=YEARLY;BYDAY=20MO)
+
+05/19/98:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+05/26/98:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+05/29/98:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+05/31/98:
+ - 09:00 -> 09:00
+ page 126: Every other month on the first and last Sunday of the month for 10 occurrences (RRULE:FREQ=MONTHLY;INTERVAL=2;COUNT=10;BYDAY=1SU,-1SU)
+
+06/04/98:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+06/05/98:
+ - 09:00 -> 09:00
+ page 126: Monthly on the first Friday for 10 occurrences (FREQ=MONTHLY;COUNT=10;BYDAY=1FR)
+
+06/10/98:
+ - 09:00 -> 09:00
+ page 128: Yearly in June and July for 10 occurrences (RRULE:FREQ=YEARLY;COUNT=10;BYMONTH=6,7)
+
+06/11/98:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+06/13/98:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+06/18/98:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+06/25/98:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+06/28/98:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+07/02/98:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+07/07/98:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+07/09/98:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+07/10/98:
+ - 09:00 -> 09:00
+ page 128: Yearly in June and July for 10 occurrences (RRULE:FREQ=YEARLY;COUNT=10;BYMONTH=6,7)
+
+07/11/98:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+07/14/98:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+07/16/98:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+07/21/98:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+07/23/98:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+07/28/98:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+07/29/98:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+07/30/98:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+08/06/98:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+08/08/98:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+08/13/98:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+08/20/98:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+08/27/98:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+08/29/98:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+09/01/98:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+09/08/98:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+09/12/98:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+09/15/98:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+09/22/98:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+09/28/98:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+09/29/98:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+10/10/98:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+10/29/98:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+11/03/98:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+11/07/98:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+11/10/98:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+11/13/98:
+ * page 129: Every Friday the 13th, forever (RRULE:FREQ=MONTHLY;BYDAY=FR;BYMONTHDAY=13)
+
+11/17/98:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+11/24/98:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+11/28/98:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+12/12/98:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+12/29/98:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+01/01/99:
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+
+01/02/99:
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+
+01/03/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+ - 08:30 -> 08:30
+ page 45: every sunday in January at 8:30 AM, every other year (FREQ=YEARLY;INTERVAL=2;BYMONTH=1;BYDAY=SU)
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+
+01/04/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+
+01/05/99:
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+01/06/99:
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+
+01/07/99:
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+
+01/08/99:
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+
+01/09/99:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+
+01/10/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+ - 08:30 -> 08:30
+ page 45: every sunday in January at 8:30 AM, every other year (FREQ=YEARLY;INTERVAL=2;BYMONTH=1;BYDAY=SU)
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+ - 09:00 -> 09:00
+ page 128: Every other year in January, February and March for 10 occurrences (RRULE:FREQ=YEARLY;INTERVAL=2;COUNT=10;BYMONTH=1,2,3)
+
+01/11/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+
+01/12/99:
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+01/13/99:
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+
+01/14/99:
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+
+01/15/99:
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+
+01/16/99:
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+
+01/17/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+ - 08:30 -> 08:30
+ page 45: every sunday in January at 8:30 AM, every other year (FREQ=YEARLY;INTERVAL=2;BYMONTH=1;BYDAY=SU)
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+
+01/18/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+
+01/19/99:
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+01/20/99:
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+
+01/21/99:
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+
+01/22/99:
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+
+01/23/99:
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+
+01/24/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+ - 08:30 -> 08:30
+ page 45: every sunday in January at 8:30 AM, every other year (FREQ=YEARLY;INTERVAL=2;BYMONTH=1;BYDAY=SU)
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+
+01/25/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+
+01/26/99:
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+01/27/99:
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+
+01/28/99:
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+
+01/29/99:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+
+01/30/99:
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+
+01/31/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+ - 08:30 -> 08:30
+ page 45: every sunday in January at 8:30 AM, every other year (FREQ=YEARLY;INTERVAL=2;BYMONTH=1;BYDAY=SU)
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+
+02/01/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+ * Every year on February 1 and 29 for eight years (RRULE:FREQ=YEARLY;UNTIL=20050131T000000Z;BYMONTH=2;BYMONTHDAY=1,29)
+
+02/07/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+02/08/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+02/10/99:
+ - 09:00 -> 09:00
+ page 128: Every other year in January, February and March for 10 occurrences (RRULE:FREQ=YEARLY;INTERVAL=2;COUNT=10;BYMONTH=1,2,3)
+
+02/13/99:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+02/14/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+02/15/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+02/21/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+02/22/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+02/26/99:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+02/28/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+03/01/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+03/02/99:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+03/04/99:
+ - 09:00 -> 09:00
+ page 129: Every Thursday in March, forever (RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=TH)
+
+03/07/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+03/08/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+03/09/99:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+03/10/99:
+ - 09:00 -> 09:00
+ page 127: Every 18 months on the 10th thru 15th of the month for 10 occurrences (RRULE:FREQ=MONTHLY;INTERVAL=18;COUNT=10;BYMONTHDAY=10,11,12,13,14,15)
+ - 09:00 -> 09:00
+ page 128: Every other year in January, February and March for 10 occurrences (RRULE:FREQ=YEARLY;INTERVAL=2;COUNT=10;BYMONTH=1,2,3)
+
+03/11/99:
+ - 09:00 -> 09:00
+ page 127: Every 18 months on the 10th thru 15th of the month for 10 occurrences (RRULE:FREQ=MONTHLY;INTERVAL=18;COUNT=10;BYMONTHDAY=10,11,12,13,14,15)
+ - 09:00 -> 09:00
+ page 129: Every Thursday in March, forever (RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=TH)
+
+03/12/99:
+ - 09:00 -> 09:00
+ page 127: Every 18 months on the 10th thru 15th of the month for 10 occurrences (RRULE:FREQ=MONTHLY;INTERVAL=18;COUNT=10;BYMONTHDAY=10,11,12,13,14,15)
+
+03/13/99:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+ - 09:00 -> 09:00
+ page 127: Every 18 months on the 10th thru 15th of the month for 10 occurrences (RRULE:FREQ=MONTHLY;INTERVAL=18;COUNT=10;BYMONTHDAY=10,11,12,13,14,15)
+
+03/14/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+03/15/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+03/16/99:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+03/18/99:
+ - 09:00 -> 09:00
+ page 129: Every Thursday in March, forever (RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=TH)
+
+03/21/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+03/22/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+03/23/99:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+03/25/99:
+ - 09:00 -> 09:00
+ page 129: Every Thursday in March, forever (RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=TH)
+
+03/28/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+ - 09:00 -> 09:00
+ Last Sunday in March, forever (RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU)
+
+03/29/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+03/30/99:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+04/04/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+04/05/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+04/10/99:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+04/11/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+04/12/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+04/18/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+04/19/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+04/25/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+04/26/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+04/28/99:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+05/02/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+05/03/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+05/04/99:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+05/08/99:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+05/09/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+05/10/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+05/11/99:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+05/16/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+05/17/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+ * page 128: Every 20th Monday of the year, forever (RRULE:FREQ=YEARLY;BYDAY=20MO)
+
+05/18/99:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+05/23/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+05/24/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+05/25/99:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+05/29/99:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+05/30/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+05/31/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+06/03/99:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+06/06/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+06/07/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+06/10/99:
+ - 09:00 -> 09:00
+ page 128: Yearly in June and July for 10 occurrences (RRULE:FREQ=YEARLY;COUNT=10;BYMONTH=6,7)
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+06/12/99:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+06/13/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+06/14/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+06/17/99:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+06/20/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+06/21/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+06/24/99:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+06/27/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+06/28/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+07/01/99:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+07/04/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+07/05/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+07/06/99:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+07/08/99:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+07/10/99:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+ - 09:00 -> 09:00
+ page 128: Yearly in June and July for 10 occurrences (RRULE:FREQ=YEARLY;COUNT=10;BYMONTH=6,7)
+
+07/11/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+07/12/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+07/13/99:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+07/15/99:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+07/18/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+07/19/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+07/20/99:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+07/22/99:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+07/25/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+07/26/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+07/27/99:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+07/29/99:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+08/01/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+08/02/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+08/05/99:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+08/07/99:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+08/08/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+08/09/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+08/12/99:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+08/13/99:
+ * page 129: Every Friday the 13th, forever (RRULE:FREQ=MONTHLY;BYDAY=FR;BYMONTHDAY=13)
+
+08/15/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+08/16/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+08/19/99:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+08/22/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+08/23/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+08/26/99:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+08/29/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+08/30/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+09/05/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+09/06/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+09/07/99:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+09/11/99:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+09/12/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+09/13/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+09/14/99:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+09/19/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+09/20/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+09/21/99:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+09/26/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+09/27/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+09/28/99:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+10/03/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+10/04/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+10/09/99:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+10/10/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+10/11/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+10/17/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+10/18/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+10/24/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+10/25/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+10/29/99:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+10/31/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+11/01/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+11/02/99:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+11/07/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+11/08/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+11/09/99:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+11/13/99:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+11/14/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+11/15/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+11/16/99:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+11/21/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+11/22/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+11/23/99:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+11/28/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+11/29/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+11/30/99:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+12/05/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+12/06/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+12/11/99:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+12/12/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+12/13/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+12/19/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+12/20/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+12/26/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+12/27/99:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+12/29/99:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+01/01/00:
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+
+01/02/00:
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+
+01/03/00:
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+
+01/04/00:
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+01/05/00:
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+
+01/06/00:
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+
+01/07/00:
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+
+01/08/00:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+
+01/09/00:
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+
+01/10/00:
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+
+01/11/00:
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+01/12/00:
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+
+01/13/00:
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+
+01/14/00:
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+
+01/15/00:
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+
+01/16/00:
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+
+01/17/00:
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+
+01/18/00:
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+01/19/00:
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+
+01/20/00:
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+
+01/21/00:
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+
+01/22/00:
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+
+01/23/00:
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+
+01/24/00:
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+
+01/25/00:
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+01/26/00:
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+
+01/27/00:
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+
+01/28/00:
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+
+01/29/00:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+
+01/30/00:
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+
+01/31/00:
+ - 09:00 -> 09:00
+ page 124(1): Every day in January for three years (FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA)
+ - 09:00 -> 09:00
+ page 124(2): Every day in January for three years (FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1)
+
+02/01/00:
+ * Every year on February 1 and 29 for eight years (RRULE:FREQ=YEARLY;UNTIL=20050131T000000Z;BYMONTH=2;BYMONTHDAY=1,29)
+
+02/12/00:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+02/27/00:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+02/29/00:
+ * Every year on February 1 and 29 for eight years (RRULE:FREQ=YEARLY;UNTIL=20050131T000000Z;BYMONTH=2;BYMONTHDAY=1,29)
+
+03/02/00:
+ - 09:00 -> 09:00
+ page 129: Every Thursday in March, forever (RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=TH)
+
+03/07/00:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+03/09/00:
+ - 09:00 -> 09:00
+ page 129: Every Thursday in March, forever (RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=TH)
+
+03/11/00:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+03/14/00:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+03/16/00:
+ - 09:00 -> 09:00
+ page 129: Every Thursday in March, forever (RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=TH)
+
+03/21/00:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+03/23/00:
+ - 09:00 -> 09:00
+ page 129: Every Thursday in March, forever (RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=TH)
+
+03/26/00:
+ - 09:00 -> 09:00
+ Last Sunday in March, forever (RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU)
+
+03/28/00:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+03/29/00:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+03/30/00:
+ - 09:00 -> 09:00
+ page 129: Every Thursday in March, forever (RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=TH)
+
+04/08/00:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+04/28/00:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+05/02/00:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+05/09/00:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+05/13/00:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+05/15/00:
+ * page 128: Every 20th Monday of the year, forever (RRULE:FREQ=YEARLY;BYDAY=20MO)
+
+05/16/00:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+05/23/00:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+05/29/00:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+05/30/00:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+06/01/00:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+06/08/00:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+06/10/00:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+ - 09:00 -> 09:00
+ page 128: Yearly in June and July for 10 occurrences (RRULE:FREQ=YEARLY;COUNT=10;BYMONTH=6,7)
+
+06/15/00:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+06/22/00:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+06/28/00:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+06/29/00:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+07/04/00:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+07/06/00:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+07/08/00:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+07/10/00:
+ - 09:00 -> 09:00
+ page 128: Yearly in June and July for 10 occurrences (RRULE:FREQ=YEARLY;COUNT=10;BYMONTH=6,7)
+
+07/11/00:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+07/13/00:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+07/18/00:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+07/20/00:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+07/25/00:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+07/27/00:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+07/29/00:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+08/03/00:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+08/10/00:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+08/12/00:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+08/17/00:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+08/24/00:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+08/29/00:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+08/31/00:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+09/05/00:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+09/09/00:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+09/12/00:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+09/19/00:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+09/26/00:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+09/28/00:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+10/07/00:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+10/13/00:
+ * page 129: Every Friday the 13th, forever (RRULE:FREQ=MONTHLY;BYDAY=FR;BYMONTHDAY=13)
+
+10/29/00:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+11/07/00:
+ * page 130: Every 4 years, the first Tuesday after a Monday in November, forever (U.S. Presidential Election day) (RRULE:FREQ=YEARLY;INTERVAL=4;BYMONTH=11;BYDAY=TU;BYMONTHDAY=2,3,4,5,6,7,8)
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+11/11/00:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+11/14/00:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+11/21/00:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+11/28/00:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+12/09/00:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+12/28/00:
+ * Last Thursday of the year every third year, forever (FREQ=YEARLY;INTERVAL=3;BYDAY=-1TH)
+
+12/29/00:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+01/01/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+01/02/01:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+01/07/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+ - 08:30 -> 08:30
+ page 45: every sunday in January at 8:30 AM, every other year (FREQ=YEARLY;INTERVAL=2;BYMONTH=1;BYDAY=SU)
+
+01/08/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+01/09/01:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+01/10/01:
+ - 09:00 -> 09:00
+ page 128: Every other year in January, February and March for 10 occurrences (RRULE:FREQ=YEARLY;INTERVAL=2;COUNT=10;BYMONTH=1,2,3)
+
+01/13/01:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+01/14/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+ - 08:30 -> 08:30
+ page 45: every sunday in January at 8:30 AM, every other year (FREQ=YEARLY;INTERVAL=2;BYMONTH=1;BYDAY=SU)
+
+01/15/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+01/16/01:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+01/21/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+ - 08:30 -> 08:30
+ page 45: every sunday in January at 8:30 AM, every other year (FREQ=YEARLY;INTERVAL=2;BYMONTH=1;BYDAY=SU)
+
+01/22/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+01/23/01:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+01/28/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+ - 08:30 -> 08:30
+ page 45: every sunday in January at 8:30 AM, every other year (FREQ=YEARLY;INTERVAL=2;BYMONTH=1;BYDAY=SU)
+
+01/29/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+01/30/01:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+02/01/01:
+ * Every year on February 1 and 29 for eight years (RRULE:FREQ=YEARLY;UNTIL=20050131T000000Z;BYMONTH=2;BYMONTHDAY=1,29)
+
+02/04/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+02/05/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+02/10/01:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+ - 09:00 -> 09:00
+ page 128: Every other year in January, February and March for 10 occurrences (RRULE:FREQ=YEARLY;INTERVAL=2;COUNT=10;BYMONTH=1,2,3)
+
+02/11/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+02/12/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+02/18/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+02/19/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+02/25/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+02/26/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+03/01/01:
+ - 09:00 -> 09:00
+ page 129: Every Thursday in March, forever (RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=TH)
+
+03/04/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+03/05/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+03/06/01:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+03/08/01:
+ - 09:00 -> 09:00
+ page 129: Every Thursday in March, forever (RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=TH)
+
+03/10/01:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+ - 09:00 -> 09:00
+ page 128: Every other year in January, February and March for 10 occurrences (RRULE:FREQ=YEARLY;INTERVAL=2;COUNT=10;BYMONTH=1,2,3)
+
+03/11/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+03/12/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+03/13/01:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+03/15/01:
+ - 09:00 -> 09:00
+ page 129: Every Thursday in March, forever (RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=TH)
+
+03/18/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+03/19/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+03/20/01:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+03/22/01:
+ - 09:00 -> 09:00
+ page 129: Every Thursday in March, forever (RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=TH)
+
+03/25/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+ - 09:00 -> 09:00
+ Last Sunday in March, forever (RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU)
+
+03/26/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+03/27/01:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+03/29/01:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+ - 09:00 -> 09:00
+ page 129: Every Thursday in March, forever (RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=TH)
+
+04/01/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+04/02/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+04/07/01:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+04/08/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+04/09/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+04/13/01:
+ * page 129: Every Friday the 13th, forever (RRULE:FREQ=MONTHLY;BYDAY=FR;BYMONTHDAY=13)
+
+04/15/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+04/16/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+04/22/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+04/23/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+04/28/01:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+04/29/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+04/30/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+05/01/01:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+05/06/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+05/07/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+05/08/01:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+05/12/01:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+05/13/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+05/14/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+ * page 128: Every 20th Monday of the year, forever (RRULE:FREQ=YEARLY;BYDAY=20MO)
+
+05/15/01:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+05/20/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+05/21/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+05/22/01:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+05/27/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+05/28/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+05/29/01:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+06/03/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+06/04/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+06/07/01:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+06/09/01:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+06/10/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+ - 09:00 -> 09:00
+ page 128: Yearly in June and July for 10 occurrences (RRULE:FREQ=YEARLY;COUNT=10;BYMONTH=6,7)
+
+06/11/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+06/14/01:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+06/17/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+06/18/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+06/21/01:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+06/24/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+06/25/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+06/28/01:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+07/01/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+07/02/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+07/03/01:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+07/05/01:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+07/07/01:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+07/08/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+07/09/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+07/10/01:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+ - 09:00 -> 09:00
+ page 128: Yearly in June and July for 10 occurrences (RRULE:FREQ=YEARLY;COUNT=10;BYMONTH=6,7)
+
+07/12/01:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+07/13/01:
+ * page 129: Every Friday the 13th, forever (RRULE:FREQ=MONTHLY;BYDAY=FR;BYMONTHDAY=13)
+
+07/15/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+07/16/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+07/17/01:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+07/19/01:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+07/22/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+07/23/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+07/24/01:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+07/26/01:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+07/29/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+07/30/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+07/31/01:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+08/02/01:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+08/05/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+08/06/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+08/09/01:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+08/11/01:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+08/12/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+08/13/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+08/16/01:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+08/19/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+08/20/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+08/23/01:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+08/26/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+08/27/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+08/29/01:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+08/30/01:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+09/02/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+09/03/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+09/04/01:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+09/08/01:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+09/09/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+09/10/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+09/11/01:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+09/16/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+09/17/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+09/18/01:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+09/23/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+09/24/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+09/25/01:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+09/28/01:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+09/30/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+10/01/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+10/07/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+10/08/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+10/13/01:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+10/14/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+10/15/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+10/21/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+10/22/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+10/28/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+10/29/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+11/04/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+11/05/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+11/06/01:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+11/10/01:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+11/11/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+11/12/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+11/13/01:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+11/18/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+11/19/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+11/20/01:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+11/25/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+11/26/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+11/27/01:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+11/28/01:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+12/02/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+12/03/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+12/08/01:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+12/09/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+12/10/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+12/16/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+12/17/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+12/23/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+12/24/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+12/29/01:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+12/30/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+12/31/01:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+01/01/02:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+01/08/02:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+01/12/02:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+01/15/02:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+01/22/02:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+01/29/02:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+02/01/02:
+ * Every year on February 1 and 29 for eight years (RRULE:FREQ=YEARLY;UNTIL=20050131T000000Z;BYMONTH=2;BYMONTHDAY=1,29)
+
+02/09/02:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+02/26/02:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+03/05/02:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+03/07/02:
+ - 09:00 -> 09:00
+ page 129: Every Thursday in March, forever (RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=TH)
+
+03/09/02:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+03/12/02:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+03/14/02:
+ - 09:00 -> 09:00
+ page 129: Every Thursday in March, forever (RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=TH)
+
+03/19/02:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+03/21/02:
+ - 09:00 -> 09:00
+ page 129: Every Thursday in March, forever (RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=TH)
+
+03/26/02:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+03/28/02:
+ - 09:00 -> 09:00
+ page 129: Every Thursday in March, forever (RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=TH)
+
+03/29/02:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+03/31/02:
+ - 09:00 -> 09:00
+ Last Sunday in March, forever (RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU)
+
+04/13/02:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+04/28/02:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+05/07/02:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+05/11/02:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+05/14/02:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+05/20/02:
+ * page 128: Every 20th Monday of the year, forever (RRULE:FREQ=YEARLY;BYDAY=20MO)
+
+05/21/02:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+05/28/02:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+05/29/02:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+06/06/02:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+06/08/02:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+06/13/02:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+06/20/02:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+06/27/02:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+06/28/02:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+07/02/02:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+07/04/02:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+07/09/02:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+07/11/02:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+07/13/02:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+07/16/02:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+07/18/02:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+07/23/02:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+07/25/02:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+07/29/02:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+07/30/02:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+08/01/02:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+08/08/02:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+08/10/02:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+08/15/02:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+08/22/02:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+08/29/02:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+09/03/02:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+09/07/02:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+09/10/02:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+09/13/02:
+ * page 129: Every Friday the 13th, forever (RRULE:FREQ=MONTHLY;BYDAY=FR;BYMONTHDAY=13)
+
+09/17/02:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+09/24/02:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+09/28/02:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+10/12/02:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+10/29/02:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+11/05/02:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+11/09/02:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+11/12/02:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+11/19/02:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+11/26/02:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+11/28/02:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+12/07/02:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+12/13/02:
+ * page 129: Every Friday the 13th, forever (RRULE:FREQ=MONTHLY;BYDAY=FR;BYMONTHDAY=13)
+
+12/29/02:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+01/05/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+ - 08:30 -> 08:30
+ page 45: every sunday in January at 8:30 AM, every other year (FREQ=YEARLY;INTERVAL=2;BYMONTH=1;BYDAY=SU)
+
+01/06/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+01/07/03:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+01/10/03:
+ - 09:00 -> 09:00
+ page 128: Every other year in January, February and March for 10 occurrences (RRULE:FREQ=YEARLY;INTERVAL=2;COUNT=10;BYMONTH=1,2,3)
+
+01/11/03:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+01/12/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+ - 08:30 -> 08:30
+ page 45: every sunday in January at 8:30 AM, every other year (FREQ=YEARLY;INTERVAL=2;BYMONTH=1;BYDAY=SU)
+
+01/13/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+01/14/03:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+01/19/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+ - 08:30 -> 08:30
+ page 45: every sunday in January at 8:30 AM, every other year (FREQ=YEARLY;INTERVAL=2;BYMONTH=1;BYDAY=SU)
+
+01/20/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+01/21/03:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+01/26/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+ - 08:30 -> 08:30
+ page 45: every sunday in January at 8:30 AM, every other year (FREQ=YEARLY;INTERVAL=2;BYMONTH=1;BYDAY=SU)
+
+01/27/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+01/28/03:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+01/29/03:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+02/01/03:
+ * Every year on February 1 and 29 for eight years (RRULE:FREQ=YEARLY;UNTIL=20050131T000000Z;BYMONTH=2;BYMONTHDAY=1,29)
+
+02/02/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+02/03/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+02/08/03:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+02/09/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+02/10/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+ - 09:00 -> 09:00
+ page 128: Every other year in January, February and March for 10 occurrences (RRULE:FREQ=YEARLY;INTERVAL=2;COUNT=10;BYMONTH=1,2,3)
+
+02/16/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+02/17/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+02/23/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+02/24/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+02/26/03:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+03/02/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+03/03/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+03/04/03:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+03/06/03:
+ - 09:00 -> 09:00
+ page 129: Every Thursday in March, forever (RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=TH)
+
+03/08/03:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+03/09/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+03/10/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+ - 09:00 -> 09:00
+ page 128: Every other year in January, February and March for 10 occurrences (RRULE:FREQ=YEARLY;INTERVAL=2;COUNT=10;BYMONTH=1,2,3)
+
+03/11/03:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+03/13/03:
+ - 09:00 -> 09:00
+ page 129: Every Thursday in March, forever (RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=TH)
+
+03/16/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+03/17/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+03/18/03:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+03/20/03:
+ - 09:00 -> 09:00
+ page 129: Every Thursday in March, forever (RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=TH)
+
+03/23/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+03/24/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+03/25/03:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+03/27/03:
+ - 09:00 -> 09:00
+ page 129: Every Thursday in March, forever (RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=TH)
+
+03/29/03:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+03/30/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+ - 09:00 -> 09:00
+ Last Sunday in March, forever (RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU)
+
+03/31/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+04/06/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+04/07/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+04/12/03:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+04/13/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+04/14/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+04/20/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+04/21/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+04/27/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+04/28/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+05/04/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+05/05/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+05/06/03:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+05/10/03:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+05/11/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+05/12/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+05/13/03:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+05/18/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+05/19/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+ * page 128: Every 20th Monday of the year, forever (RRULE:FREQ=YEARLY;BYDAY=20MO)
+
+05/20/03:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+05/25/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+05/26/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+05/27/03:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+05/29/03:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+06/01/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+06/02/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+06/05/03:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+06/07/03:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+06/08/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+06/09/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+06/12/03:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+06/13/03:
+ * page 129: Every Friday the 13th, forever (RRULE:FREQ=MONTHLY;BYDAY=FR;BYMONTHDAY=13)
+
+06/15/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+06/16/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+06/19/03:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+06/22/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+06/23/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+06/26/03:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+06/28/03:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+06/29/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+06/30/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+07/01/03:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+07/03/03:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+07/06/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+07/07/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+07/08/03:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+07/10/03:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+07/12/03:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+07/13/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+07/14/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+07/15/03:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+07/17/03:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+07/20/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+07/21/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+07/22/03:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+07/24/03:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+07/27/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+07/28/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+07/29/03:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+07/31/03:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+08/03/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+08/04/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+08/07/03:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+08/09/03:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+08/10/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+08/11/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+08/14/03:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+08/17/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+08/18/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+08/21/03:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+08/24/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+08/25/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+08/28/03:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+08/29/03:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+08/31/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+09/01/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+09/02/03:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+09/07/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+09/08/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+09/09/03:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+09/13/03:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+09/14/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+09/15/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+09/16/03:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+09/21/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+09/22/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+09/23/03:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+09/28/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+09/29/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+09/30/03:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+10/05/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+10/06/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+10/11/03:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+10/12/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+10/13/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+10/19/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+10/20/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+10/26/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+10/27/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+10/29/03:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+11/02/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+11/03/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+11/04/03:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+11/08/03:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+11/09/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+11/10/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+11/11/03:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+11/16/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+11/17/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+11/18/03:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+11/23/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+11/24/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+11/25/03:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+11/28/03:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+11/30/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+12/01/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+12/07/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+12/08/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+12/13/03:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+12/14/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+12/15/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+12/21/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+12/22/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+12/25/03:
+ * Last Thursday of the year every third year, forever (FREQ=YEARLY;INTERVAL=3;BYDAY=-1TH)
+
+12/28/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+12/29/03:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+01/06/04:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+01/10/04:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+01/13/04:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+01/20/04:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+01/27/04:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+01/29/04:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+02/01/04:
+ * Every year on February 1 and 29 for eight years (RRULE:FREQ=YEARLY;UNTIL=20050131T000000Z;BYMONTH=2;BYMONTHDAY=1,29)
+
+02/07/04:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+02/13/04:
+ * page 129: Every Friday the 13th, forever (RRULE:FREQ=MONTHLY;BYDAY=FR;BYMONTHDAY=13)
+
+02/27/04:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+02/29/04:
+ * Every year on February 1 and 29 for eight years (RRULE:FREQ=YEARLY;UNTIL=20050131T000000Z;BYMONTH=2;BYMONTHDAY=1,29)
+
+03/02/04:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+03/04/04:
+ - 09:00 -> 09:00
+ page 129: Every Thursday in March, forever (RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=TH)
+
+03/09/04:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+03/11/04:
+ - 09:00 -> 09:00
+ page 129: Every Thursday in March, forever (RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=TH)
+
+03/13/04:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+03/16/04:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+03/18/04:
+ - 09:00 -> 09:00
+ page 129: Every Thursday in March, forever (RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=TH)
+
+03/23/04:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+03/25/04:
+ - 09:00 -> 09:00
+ page 129: Every Thursday in March, forever (RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=TH)
+
+03/28/04:
+ - 09:00 -> 09:00
+ Last Sunday in March, forever (RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU)
+
+03/29/04:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+03/30/04:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+04/10/04:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+04/28/04:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+05/04/04:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+05/08/04:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+05/11/04:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+05/17/04:
+ * page 128: Every 20th Monday of the year, forever (RRULE:FREQ=YEARLY;BYDAY=20MO)
+
+05/18/04:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+05/25/04:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+05/29/04:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+06/03/04:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+06/10/04:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+06/12/04:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+06/17/04:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+06/24/04:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+06/28/04:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+07/01/04:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+07/06/04:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+07/08/04:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+07/10/04:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+07/13/04:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+07/15/04:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+07/20/04:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+07/22/04:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+07/27/04:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+07/29/04:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+08/05/04:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+08/07/04:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+08/12/04:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+08/13/04:
+ * page 129: Every Friday the 13th, forever (RRULE:FREQ=MONTHLY;BYDAY=FR;BYMONTHDAY=13)
+
+08/19/04:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+08/26/04:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+08/29/04:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+09/07/04:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+09/11/04:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+09/14/04:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+09/21/04:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+09/28/04:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+10/09/04:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+10/29/04:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+11/02/04:
+ * page 130: Every 4 years, the first Tuesday after a Monday in November, forever (U.S. Presidential Election day) (RRULE:FREQ=YEARLY;INTERVAL=4;BYMONTH=11;BYDAY=TU;BYMONTHDAY=2,3,4,5,6,7,8)
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+11/09/04:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+11/13/04:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+11/16/04:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+11/23/04:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+11/28/04:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+11/30/04:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+12/11/04:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+12/29/04:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+01/02/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+ - 08:30 -> 08:30
+ page 45: every sunday in January at 8:30 AM, every other year (FREQ=YEARLY;INTERVAL=2;BYMONTH=1;BYDAY=SU)
+
+01/03/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+01/04/05:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+01/08/05:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+01/09/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+ - 08:30 -> 08:30
+ page 45: every sunday in January at 8:30 AM, every other year (FREQ=YEARLY;INTERVAL=2;BYMONTH=1;BYDAY=SU)
+
+01/10/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+01/11/05:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+01/16/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+ - 08:30 -> 08:30
+ page 45: every sunday in January at 8:30 AM, every other year (FREQ=YEARLY;INTERVAL=2;BYMONTH=1;BYDAY=SU)
+
+01/17/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+01/18/05:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+01/23/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+ - 08:30 -> 08:30
+ page 45: every sunday in January at 8:30 AM, every other year (FREQ=YEARLY;INTERVAL=2;BYMONTH=1;BYDAY=SU)
+
+01/24/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+01/25/05:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+01/29/05:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+01/30/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+ - 08:30 -> 08:30
+ page 45: every sunday in January at 8:30 AM, every other year (FREQ=YEARLY;INTERVAL=2;BYMONTH=1;BYDAY=SU)
+
+01/31/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+02/06/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+02/07/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+02/12/05:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+02/13/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+02/14/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+02/20/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+02/21/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+02/26/05:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+02/27/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+02/28/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+03/01/05:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+03/03/05:
+ - 09:00 -> 09:00
+ page 129: Every Thursday in March, forever (RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=TH)
+
+03/06/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+03/07/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+03/08/05:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+03/10/05:
+ - 09:00 -> 09:00
+ page 129: Every Thursday in March, forever (RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=TH)
+
+03/12/05:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+03/13/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+03/14/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+03/15/05:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+03/17/05:
+ - 09:00 -> 09:00
+ page 129: Every Thursday in March, forever (RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=TH)
+
+03/20/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+03/21/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+03/22/05:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+03/24/05:
+ - 09:00 -> 09:00
+ page 129: Every Thursday in March, forever (RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=TH)
+
+03/27/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+ - 09:00 -> 09:00
+ Last Sunday in March, forever (RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU)
+
+03/28/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+03/29/05:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+03/31/05:
+ - 09:00 -> 09:00
+ page 129: Every Thursday in March, forever (RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=TH)
+
+04/03/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+04/04/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+04/09/05:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+04/10/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+04/11/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+04/17/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+04/18/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+04/24/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+04/25/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+04/28/05:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+05/01/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+05/02/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+05/03/05:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+05/07/05:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+05/08/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+05/09/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+05/10/05:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+05/13/05:
+ * page 129: Every Friday the 13th, forever (RRULE:FREQ=MONTHLY;BYDAY=FR;BYMONTHDAY=13)
+
+05/15/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+05/16/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+ * page 128: Every 20th Monday of the year, forever (RRULE:FREQ=YEARLY;BYDAY=20MO)
+
+05/17/05:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+05/22/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+05/23/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+05/24/05:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+05/29/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+05/30/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+05/31/05:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+06/02/05:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+06/05/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+06/06/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+06/09/05:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+06/11/05:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+06/12/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+06/13/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+06/16/05:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+06/19/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+06/20/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+06/23/05:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+06/26/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+06/27/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+06/28/05:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+06/30/05:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+07/03/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+07/04/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+07/05/05:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+07/07/05:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+07/09/05:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+07/10/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+07/11/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+07/12/05:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+07/14/05:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+07/17/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+07/18/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+07/19/05:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+07/21/05:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+07/24/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+07/25/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+07/26/05:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+07/28/05:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+07/29/05:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+07/31/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+08/01/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+08/04/05:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+08/07/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+08/08/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+08/11/05:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+08/13/05:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+08/14/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+08/15/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+08/18/05:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+08/21/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+08/22/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+08/25/05:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+08/28/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+08/29/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+09/04/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+09/05/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+09/06/05:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+09/10/05:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+09/11/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+09/12/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+09/13/05:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+09/18/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+09/19/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+09/20/05:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+09/25/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+09/26/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+09/27/05:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+09/28/05:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+10/02/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+10/03/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+10/08/05:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+10/09/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+10/10/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+10/16/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+10/17/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+10/23/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+10/24/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+10/29/05:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+10/30/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+10/31/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+11/01/05:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+11/06/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+11/07/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+11/08/05:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+11/12/05:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+11/13/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+11/14/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+11/15/05:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+11/20/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+11/21/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+11/22/05:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+11/27/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+11/28/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+11/29/05:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+12/04/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+12/05/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+12/10/05:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+12/11/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+12/12/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+12/18/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+12/19/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+12/25/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+12/26/05:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+12/29/05:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+01/03/06:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+01/07/06:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+01/10/06:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+01/13/06:
+ * page 129: Every Friday the 13th, forever (RRULE:FREQ=MONTHLY;BYDAY=FR;BYMONTHDAY=13)
+
+01/17/06:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+01/24/06:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+01/29/06:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+01/31/06:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+02/11/06:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+02/26/06:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+03/02/06:
+ - 09:00 -> 09:00
+ page 129: Every Thursday in March, forever (RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=TH)
+
+03/07/06:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+03/09/06:
+ - 09:00 -> 09:00
+ page 129: Every Thursday in March, forever (RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=TH)
+
+03/11/06:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+03/14/06:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+03/16/06:
+ - 09:00 -> 09:00
+ page 129: Every Thursday in March, forever (RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=TH)
+
+03/21/06:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+03/23/06:
+ - 09:00 -> 09:00
+ page 129: Every Thursday in March, forever (RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=TH)
+
+03/26/06:
+ - 09:00 -> 09:00
+ Last Sunday in March, forever (RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU)
+
+03/28/06:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+03/29/06:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+03/30/06:
+ - 09:00 -> 09:00
+ page 129: Every Thursday in March, forever (RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=TH)
+
+04/08/06:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+04/28/06:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+05/02/06:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+05/09/06:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+05/13/06:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+05/15/06:
+ * page 128: Every 20th Monday of the year, forever (RRULE:FREQ=YEARLY;BYDAY=20MO)
+
+05/16/06:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+05/23/06:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+05/29/06:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+05/30/06:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+06/01/06:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+06/08/06:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+06/10/06:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+06/15/06:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+06/22/06:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+06/28/06:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+06/29/06:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+07/04/06:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+07/06/06:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+07/08/06:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+07/11/06:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+07/13/06:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+07/18/06:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+07/20/06:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+07/25/06:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+07/27/06:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+07/29/06:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+08/03/06:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+08/10/06:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+08/12/06:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+08/17/06:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+08/24/06:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+08/29/06:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+08/31/06:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+09/05/06:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+09/09/06:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+09/12/06:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+09/19/06:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+09/26/06:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+09/28/06:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+10/07/06:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+10/13/06:
+ * page 129: Every Friday the 13th, forever (RRULE:FREQ=MONTHLY;BYDAY=FR;BYMONTHDAY=13)
+
+10/29/06:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+11/07/06:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+11/11/06:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+11/14/06:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+11/21/06:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+11/28/06:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+12/09/06:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+12/28/06:
+ * Last Thursday of the year every third year, forever (FREQ=YEARLY;INTERVAL=3;BYDAY=-1TH)
+
+12/29/06:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+01/01/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+01/02/07:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+01/07/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+ - 08:30 -> 08:30
+ page 45: every sunday in January at 8:30 AM, every other year (FREQ=YEARLY;INTERVAL=2;BYMONTH=1;BYDAY=SU)
+
+01/08/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+01/09/07:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+01/13/07:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+01/14/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+ - 08:30 -> 08:30
+ page 45: every sunday in January at 8:30 AM, every other year (FREQ=YEARLY;INTERVAL=2;BYMONTH=1;BYDAY=SU)
+
+01/15/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+ * page 132: An example where an invalid date (i.e. February 30) is ignored (RRULE:FREQ=MONTHLY;BYMONTHDAY=15,30;COUNT=5)
+
+01/16/07:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+01/21/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+ - 08:30 -> 08:30
+ page 45: every sunday in January at 8:30 AM, every other year (FREQ=YEARLY;INTERVAL=2;BYMONTH=1;BYDAY=SU)
+
+01/22/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+01/23/07:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+01/28/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+ - 08:30 -> 08:30
+ page 45: every sunday in January at 8:30 AM, every other year (FREQ=YEARLY;INTERVAL=2;BYMONTH=1;BYDAY=SU)
+
+01/29/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+01/30/07:
+ * page 132: An example where an invalid date (i.e. February 30) is ignored (RRULE:FREQ=MONTHLY;BYMONTHDAY=15,30;COUNT=5)
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+02/04/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+02/05/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+02/10/07:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+02/11/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+02/12/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+02/15/07:
+ * page 132: An example where an invalid date (i.e. February 30) is ignored (RRULE:FREQ=MONTHLY;BYMONTHDAY=15,30;COUNT=5)
+
+02/18/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+02/19/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+02/25/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+02/26/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+03/01/07:
+ - 09:00 -> 09:00
+ page 129: Every Thursday in March, forever (RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=TH)
+
+03/04/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+03/05/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+03/06/07:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+03/08/07:
+ - 09:00 -> 09:00
+ page 129: Every Thursday in March, forever (RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=TH)
+
+03/10/07:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+03/11/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+03/12/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+03/13/07:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+03/15/07:
+ * page 132: An example where an invalid date (i.e. February 30) is ignored (RRULE:FREQ=MONTHLY;BYMONTHDAY=15,30;COUNT=5)
+ - 09:00 -> 09:00
+ page 129: Every Thursday in March, forever (RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=TH)
+
+03/18/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+03/19/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+03/20/07:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+03/22/07:
+ - 09:00 -> 09:00
+ page 129: Every Thursday in March, forever (RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=TH)
+
+03/25/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+ - 09:00 -> 09:00
+ Last Sunday in March, forever (RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU)
+
+03/26/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+03/27/07:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+03/29/07:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+ - 09:00 -> 09:00
+ page 129: Every Thursday in March, forever (RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=TH)
+
+03/30/07:
+ * page 132: An example where an invalid date (i.e. February 30) is ignored (RRULE:FREQ=MONTHLY;BYMONTHDAY=15,30;COUNT=5)
+
+04/01/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+04/02/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+04/07/07:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+04/08/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+04/09/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+04/13/07:
+ * page 129: Every Friday the 13th, forever (RRULE:FREQ=MONTHLY;BYDAY=FR;BYMONTHDAY=13)
+
+04/15/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+04/16/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+04/22/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+04/23/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+04/28/07:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+04/29/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+04/30/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+05/01/07:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+05/06/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+05/07/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+05/08/07:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+05/12/07:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+05/13/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+05/14/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+ * page 128: Every 20th Monday of the year, forever (RRULE:FREQ=YEARLY;BYDAY=20MO)
+
+05/15/07:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+05/20/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+05/21/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+05/22/07:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+05/27/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+05/28/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+05/29/07:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+06/03/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+06/04/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+06/07/07:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+06/09/07:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+06/10/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+06/11/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+06/14/07:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+06/17/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+06/18/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+06/21/07:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+06/24/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+06/25/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+06/28/07:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+07/01/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+07/02/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+07/03/07:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+07/05/07:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+07/07/07:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+07/08/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+07/09/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+07/10/07:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+07/12/07:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+07/13/07:
+ * page 129: Every Friday the 13th, forever (RRULE:FREQ=MONTHLY;BYDAY=FR;BYMONTHDAY=13)
+
+07/15/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+07/16/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+07/17/07:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+07/19/07:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+07/22/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+07/23/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+07/24/07:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+07/26/07:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+07/29/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+07/30/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+07/31/07:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+08/02/07:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+08/05/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+08/06/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+08/09/07:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+08/11/07:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+08/12/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+08/13/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+08/16/07:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+08/19/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+08/20/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+08/23/07:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+08/26/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+08/27/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+08/29/07:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+08/30/07:
+ - 09:00 -> 09:00
+ page 129: Every Thursday, but only during June, July and August, forever (RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8)
+
+09/02/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+09/03/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+09/04/07:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+09/08/07:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+09/09/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+09/10/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+09/11/07:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+09/16/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+09/17/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+09/18/07:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+09/23/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+09/24/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+09/25/07:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+09/28/07:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+09/30/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+10/01/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+10/07/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+10/08/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+10/13/07:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+10/14/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+10/15/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+10/21/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+10/22/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+10/28/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+10/29/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+11/04/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+11/05/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+11/06/07:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+11/10/07:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+11/11/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+11/12/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+11/13/07:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+11/18/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+11/19/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+11/20/07:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+11/25/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+11/26/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+11/27/07:
+ - 09:00 -> 09:00
+ page 127: Every Tuesday, every other month (RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU)
+
+11/28/07:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+12/02/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+12/03/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+12/08/07:
+ * page 130: The first Saturday that follows the first Sunday of the month, forever (RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13)
+
+12/09/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+12/10/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+12/16/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+12/17/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+12/23/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+12/24/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+12/29/07:
+ * page 127: Monthly on the third-to-last day of the month, forever (RRULE:FREQ=MONTHLY;BYMONTHDAY=-3)
+
+12/30/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+12/31/07:
+ * Every Sunday and Monday, every other year (FREQ=YEARLY;INTERVAL=2;BYDAY=SU,MO)
+
+Floating point exception?
+08/01/20:
+ - 08:41 -> 10:11
+ negative ordered weekday may not exist
+No Floating point exception on November 1, 2020
+EOD
+else
+ ./run-test "$0"
+fi
diff --git a/test/recur-010.sh b/test/recur-010.sh
new file mode 100755
index 0000000..5567a40
--- /dev/null
+++ b/test/recur-010.sh
@@ -0,0 +1,51 @@
+#!/bin/sh
+# Calcurse support of recurrence rules does not include the rule part WKST (weekstart),
+# but calcurse configuration does allow a choice between Monday and Sunday.
+
+. "${TEST_INIT:-./test-init.sh}"
+
+if [ "$1" = 'actual' ]; then
+ TMP=tmp
+ mkdir "$TMP"
+ cp "$DATA_DIR"/conf "$TMP"
+ sed -n '/page 131/p' "$DATA_DIR"/rfc5545 > "$TMP"/apts
+ "$CALCURSE" -D "$TMP" -Q --filter-type cal --startday=08/01/1997 --range=31
+ sed 's/=monday/=sunday/' "$DATA_DIR"/conf > "$TMP"/conf
+ "$CALCURSE" -D "$TMP" -Q --filter-type cal --startday=08/01/1997 --range=31
+ rm -rf "$TMP"
+elif [ "$1" = 'expected' ]; then
+ cat <<EOD
+08/05/97:
+ - 09:00 -> 09:00
+ page 131: An example where the days generated makes a difference because of weekstart (RRULE:FREQ=WEEKLY;INTERVAL=2;COUNT=4;BYDAY=TU,SU)
+
+08/10/97:
+ - 09:00 -> 09:00
+ page 131: An example where the days generated makes a difference because of weekstart (RRULE:FREQ=WEEKLY;INTERVAL=2;COUNT=4;BYDAY=TU,SU)
+
+08/19/97:
+ - 09:00 -> 09:00
+ page 131: An example where the days generated makes a difference because of weekstart (RRULE:FREQ=WEEKLY;INTERVAL=2;COUNT=4;BYDAY=TU,SU)
+
+08/24/97:
+ - 09:00 -> 09:00
+ page 131: An example where the days generated makes a difference because of weekstart (RRULE:FREQ=WEEKLY;INTERVAL=2;COUNT=4;BYDAY=TU,SU)
+08/05/97:
+ - 09:00 -> 09:00
+ page 131: An example where the days generated makes a difference because of weekstart (RRULE:FREQ=WEEKLY;INTERVAL=2;COUNT=4;BYDAY=TU,SU)
+
+08/17/97:
+ - 09:00 -> 09:00
+ page 131: An example where the days generated makes a difference because of weekstart (RRULE:FREQ=WEEKLY;INTERVAL=2;COUNT=4;BYDAY=TU,SU)
+
+08/19/97:
+ - 09:00 -> 09:00
+ page 131: An example where the days generated makes a difference because of weekstart (RRULE:FREQ=WEEKLY;INTERVAL=2;COUNT=4;BYDAY=TU,SU)
+
+08/31/97:
+ - 09:00 -> 09:00
+ page 131: An example where the days generated makes a difference because of weekstart (RRULE:FREQ=WEEKLY;INTERVAL=2;COUNT=4;BYDAY=TU,SU)
+EOD
+else
+ ./run-test "$0"
+fi