diff options
| author | Glenn Morris | 2008-03-16 01:21:25 +0000 |
|---|---|---|
| committer | Glenn Morris | 2008-03-16 01:21:25 +0000 |
| commit | f8e9107c532cd857b2e5ca471d94e1bf5dc3fb35 (patch) | |
| tree | 5feb52f1ffda266301480b3fc87d9bc41e9dfa2f | |
| parent | 30864d5f804c54bd1537d07a8e1aabf8e707f73e (diff) | |
| download | emacs-f8e9107c532cd857b2e5ca471d94e1bf5dc3fb35.tar.gz emacs-f8e9107c532cd857b2e5ca471d94e1bf5dc3fb35.zip | |
Craig Markwardt <Craig.Markwardt at nasa.gov>
(icalendar-recurring-start-year): New variable.
(icalendar--diarytime-to-isotime): Fix treatment of 12:00pm - 12:59pm.
(icalendar-export-region): Ignore hidden diary entries.
(icalendar--convert-ordinary-to-ical): Fix case where event
spans across midnight boundary.
(icalendar-first-weekday-of-year): New function.
(icalendar--convert-weekly-to-ical): Allow user-selectable start
year for recurring events (Mozilla calendars do not propagate
recurring events forever, so year 2000 start date was not working).
(icalendar--convert-yearly-to-ical): Remove extra spaces in
formatting of BYMONTH and BYMONTHDAY (not allowed by ical spec).
| -rw-r--r-- | lisp/calendar/icalendar.el | 72 |
1 files changed, 55 insertions, 17 deletions
diff --git a/lisp/calendar/icalendar.el b/lisp/calendar/icalendar.el index 62cc247e8de..e202d957f08 100644 --- a/lisp/calendar/icalendar.el +++ b/lisp/calendar/icalendar.el | |||
| @@ -195,6 +195,15 @@ the class." | |||
| 195 | :type 'string | 195 | :type 'string |
| 196 | :group 'icalendar) | 196 | :group 'icalendar) |
| 197 | 197 | ||
| 198 | (defcustom icalendar-recurring-start-year | ||
| 199 | 2005 | ||
| 200 | "Start year for recurring events. | ||
| 201 | Some calendar browsers only propagate recurring events for | ||
| 202 | several years beyond the start time. Set this string to a year | ||
| 203 | just before the start of your personal calendar." | ||
| 204 | :type 'integer | ||
| 205 | :group 'icalendar) | ||
| 206 | |||
| 198 | (defvar icalendar-debug nil | 207 | (defvar icalendar-debug nil |
| 199 | "Enable icalendar debug messages.") | 208 | "Enable icalendar debug messages.") |
| 200 | 209 | ||
| @@ -771,7 +780,8 @@ would be \"pm\"." | |||
| 771 | (if timestring | 780 | (if timestring |
| 772 | (let ((starttimenum (read (icalendar--rris ":" "" timestring)))) | 781 | (let ((starttimenum (read (icalendar--rris ":" "" timestring)))) |
| 773 | ;; take care of am/pm style | 782 | ;; take care of am/pm style |
| 774 | (if (and ampmstring (string= "pm" ampmstring)) | 783 | ;; Be sure *not* to convert 12:00pm - 12:59pm to 2400-2459 |
| 784 | (if (and ampmstring (string= "pm" ampmstring) (< starttimenum 1200)) | ||
| 775 | (setq starttimenum (+ starttimenum 1200))) | 785 | (setq starttimenum (+ starttimenum 1200))) |
| 776 | (format "T%04d00" starttimenum)) | 786 | (format "T%04d00" starttimenum)) |
| 777 | nil)) | 787 | nil)) |
| @@ -837,7 +847,8 @@ FExport diary data into iCalendar file: ") | |||
| 837 | (save-excursion | 847 | (save-excursion |
| 838 | (goto-char min) | 848 | (goto-char min) |
| 839 | (while (re-search-forward | 849 | (while (re-search-forward |
| 840 | "^\\([^ \t\n].+\\)\\(\\(\n[ \t].*\\)*\\)" max t) | 850 | ;; ignores hidden entries beginning with "&" |
| 851 | "^\\([^ \t\n&#].+\\)\\(\\(\n[ \t].*\\)*\\)" max t) | ||
| 841 | (setq entry-main (match-string 1)) | 852 | (setq entry-main (match-string 1)) |
| 842 | (if (match-beginning 2) | 853 | (if (match-beginning 2) |
| 843 | (setq entry-rest (match-string 2)) | 854 | (setq entry-rest (match-string 2)) |
| @@ -1040,6 +1051,7 @@ entries. ENTRY-MAIN is the first line of the diary entry." | |||
| 1040 | datetime)) | 1051 | datetime)) |
| 1041 | (endisostring (icalendar--datestring-to-isodate | 1052 | (endisostring (icalendar--datestring-to-isodate |
| 1042 | datetime 1)) | 1053 | datetime 1)) |
| 1054 | (endisostring1) | ||
| 1043 | (starttimestring (icalendar--diarytime-to-isotime | 1055 | (starttimestring (icalendar--diarytime-to-isotime |
| 1044 | (if (match-beginning 3) | 1056 | (if (match-beginning 3) |
| 1045 | (substring entry-main | 1057 | (substring entry-main |
| @@ -1069,13 +1081,27 @@ entries. ENTRY-MAIN is the first line of the diary entry." | |||
| 1069 | 1081 | ||
| 1070 | (unless startisostring | 1082 | (unless startisostring |
| 1071 | (error "Could not parse date")) | 1083 | (error "Could not parse date")) |
| 1084 | |||
| 1085 | ;; If only start-date is specified, then end-date is next day, | ||
| 1086 | ;; otherwise it is same day. | ||
| 1087 | (setq endisostring1 (if starttimestring | ||
| 1088 | startisostring | ||
| 1089 | endisostring)) | ||
| 1090 | |||
| 1072 | (when starttimestring | 1091 | (when starttimestring |
| 1073 | (unless endtimestring | 1092 | (unless endtimestring |
| 1074 | (let ((time | 1093 | (let ((time |
| 1075 | (read (icalendar--rris "^T0?" "" | 1094 | (read (icalendar--rris "^T0?" "" |
| 1076 | starttimestring)))) | 1095 | starttimestring)))) |
| 1096 | (if (< time 230000) | ||
| 1097 | ;; Case: ends on same day | ||
| 1077 | (setq endtimestring (format "T%06d" | 1098 | (setq endtimestring (format "T%06d" |
| 1078 | (+ 10000 time)))))) | 1099 | (+ 10000 time))) |
| 1100 | ;; Case: ends on next day | ||
| 1101 | (setq endtimestring (format "T%06d" | ||
| 1102 | (- time 230000))) | ||
| 1103 | (setq endisostring1 endisostring)) ))) | ||
| 1104 | |||
| 1079 | (list (concat "\nDTSTART;" | 1105 | (list (concat "\nDTSTART;" |
| 1080 | (if starttimestring "VALUE=DATE-TIME:" | 1106 | (if starttimestring "VALUE=DATE-TIME:" |
| 1081 | "VALUE=DATE:") | 1107 | "VALUE=DATE:") |
| @@ -1084,14 +1110,22 @@ entries. ENTRY-MAIN is the first line of the diary entry." | |||
| 1084 | "\nDTEND;" | 1110 | "\nDTEND;" |
| 1085 | (if endtimestring "VALUE=DATE-TIME:" | 1111 | (if endtimestring "VALUE=DATE-TIME:" |
| 1086 | "VALUE=DATE:") | 1112 | "VALUE=DATE:") |
| 1087 | (if starttimestring | 1113 | endisostring1 |
| 1088 | startisostring | ||
| 1089 | endisostring) | ||
| 1090 | (or endtimestring "")) | 1114 | (or endtimestring "")) |
| 1091 | summary)) | 1115 | summary)) |
| 1092 | ;; no match | 1116 | ;; no match |
| 1093 | nil)) | 1117 | nil)) |
| 1094 | 1118 | ||
| 1119 | (defun icalendar-first-weekday-of-year (abbrevweekday year &optional offset) | ||
| 1120 | "Find the first WEEKDAY in a given YEAR." | ||
| 1121 | (let* ((j2000 (calendar-absolute-from-gregorian '(1 2 2000))) | ||
| 1122 | (juser (calendar-absolute-from-gregorian (list 1 1 year))) | ||
| 1123 | (wdayjan1 (mod (- juser j2000) 7)) | ||
| 1124 | (wdayuser (icalendar--get-weekday-number abbrevweekday)) | ||
| 1125 | (dayoff (+ wdayuser 1 (- wdayjan1) (or offset 0)))) | ||
| 1126 | (if (<= dayoff 0) (setq dayoff (+ dayoff 7))) | ||
| 1127 | (list year 1 dayoff))) | ||
| 1128 | |||
| 1095 | (defun icalendar--convert-weekly-to-ical (nonmarker entry-main) | 1129 | (defun icalendar--convert-weekly-to-ical (nonmarker entry-main) |
| 1096 | "Convert weekly diary entry to icalendar format. | 1130 | "Convert weekly diary entry to icalendar format. |
| 1097 | NONMARKER is a regular expression matching the start of non-marking | 1131 | NONMARKER is a regular expression matching the start of non-marking |
| @@ -1150,21 +1184,23 @@ entries. ENTRY-MAIN is the first line of the diary entry." | |||
| 1150 | (if starttimestring | 1184 | (if starttimestring |
| 1151 | "VALUE=DATE-TIME:" | 1185 | "VALUE=DATE-TIME:" |
| 1152 | "VALUE=DATE:") | 1186 | "VALUE=DATE:") |
| 1153 | ;; find the correct week day, | 1187 | ;; Find the first requested weekday of the |
| 1154 | ;; 1st january 2000 was a saturday | 1188 | ;; start year |
| 1155 | (format | 1189 | (apply 'format |
| 1156 | "200001%02d" | 1190 | "%04d%02d%02d" |
| 1157 | (+ (icalendar--get-weekday-number day) 2)) | 1191 | (icalendar-first-weekday-of-year day |
| 1192 | icalendar-recurring-start-year)) | ||
| 1158 | (or starttimestring "") | 1193 | (or starttimestring "") |
| 1159 | "\nDTEND;" | 1194 | "\nDTEND;" |
| 1160 | (if endtimestring | 1195 | (if endtimestring |
| 1161 | "VALUE=DATE-TIME:" | 1196 | "VALUE=DATE-TIME:" |
| 1162 | "VALUE=DATE:") | 1197 | "VALUE=DATE:") |
| 1163 | (format | 1198 | (apply 'format |
| 1164 | "200001%02d" | 1199 | "%04d%02d%02d" |
| 1165 | ;; end is non-inclusive! | 1200 | ;; end is non-inclusive! |
| 1166 | (+ (icalendar--get-weekday-number day) | 1201 | (icalendar-first-weekday-of-year day |
| 1167 | (if endtimestring 2 3))) | 1202 | icalendar-recurring-start-year |
| 1203 | (if endtimestring 0 1))) | ||
| 1168 | (or endtimestring "") | 1204 | (or endtimestring "") |
| 1169 | "\nRRULE:FREQ=WEEKLY;INTERVAL=1;BYDAY=" | 1205 | "\nRRULE:FREQ=WEEKLY;INTERVAL=1;BYDAY=" |
| 1170 | day) | 1206 | day) |
| @@ -1245,9 +1281,11 @@ entries. ENTRY-MAIN is the first line of the diary entry." | |||
| 1245 | (if endtimestring 0 1)) | 1281 | (if endtimestring 0 1)) |
| 1246 | (or endtimestring "") | 1282 | (or endtimestring "") |
| 1247 | "\nRRULE:FREQ=YEARLY;INTERVAL=1;BYMONTH=" | 1283 | "\nRRULE:FREQ=YEARLY;INTERVAL=1;BYMONTH=" |
| 1248 | (format "%2d" month) | 1284 | ;; Removed %2d formatting string since spaces |
| 1285 | ;; are not allowed | ||
| 1286 | (format "%d" month) | ||
| 1249 | ";BYMONTHDAY=" | 1287 | ";BYMONTHDAY=" |
| 1250 | (format "%2d" day)) | 1288 | (format "%d" day)) |
| 1251 | summary)) | 1289 | summary)) |
| 1252 | ;; no match | 1290 | ;; no match |
| 1253 | nil)) | 1291 | nil)) |