+(defun icalendar--convert-to-ical (nonmarker entry-main)
+ "Convert a diary entry to icalendar format.
+NONMARKER is a regular expression matching the start of non-marking
+entries. ENTRY-MAIN is the first line of the diary entry."
+ (or
+ ;; anniversaries -- %%(diary-anniversary ...)
+ (icalendar--convert-anniversary-to-ical nonmarker entry-main)
+ ;; cyclic events -- %%(diary-cyclic ...)
+ (icalendar--convert-cyclic-to-ical nonmarker entry-main)
+ ;; diary-date -- %%(diary-date ...)
+ (icalendar--convert-date-to-ical nonmarker entry-main)
+ ;; float events -- %%(diary-float ...)
+ (icalendar--convert-float-to-ical nonmarker entry-main)
+ ;; block events -- %%(diary-block ...)
+ (icalendar--convert-block-to-ical nonmarker entry-main)
+ ;; other sexp diary entries
+ (icalendar--convert-sexp-to-ical nonmarker entry-main)
+ ;; weekly by day -- Monday 8:30 Team meeting
+ (icalendar--convert-weekly-to-ical nonmarker entry-main)
+ ;; yearly by day -- 1 May Tag der Arbeit
+ (icalendar--convert-yearly-to-ical nonmarker entry-main)
+ ;; "ordinary" events, start and end time given
+ ;; 1 Feb 2003 blah
+ (icalendar--convert-ordinary-to-ical nonmarker entry-main)
+ ;; everything else
+ ;; Oops! what's that?
+ (error "Could not parse entry")))
+
+(defun icalendar--parse-summary-and-rest (summary-and-rest)
+ "Parse SUMMARY-AND-REST from a diary to fill iCalendar properties."
+ (save-match-data
+ (let* ((s icalendar-import-format)
+ (p-cla (or (string-match "%c" icalendar-import-format) -1))
+ (p-des (or (string-match "%d" icalendar-import-format) -1))
+ (p-loc (or (string-match "%l" icalendar-import-format) -1))
+ (p-org (or (string-match "%o" icalendar-import-format) -1))
+ (p-sum (or (string-match "%s" icalendar-import-format) -1))
+ (p-sta (or (string-match "%t" icalendar-import-format) -1))
+ (p-url (or (string-match "%u" icalendar-import-format) -1))
+ (p-list (sort (list p-cla p-des p-loc p-org p-sta p-sum p-url) '<))
+ pos-cla pos-des pos-loc pos-org pos-sta pos-sum pos-url)
+ (dotimes (i (length p-list))
+ (cond ((and (>= p-cla 0) (= (nth i p-list) p-cla))
+ (setq pos-cla (+ 2 (* 2 i))))
+ ((and (>= p-des 0) (= (nth i p-list) p-des))
+ (setq pos-des (+ 2 (* 2 i))))
+ ((and (>= p-loc 0) (= (nth i p-list) p-loc))
+ (setq pos-loc (+ 2 (* 2 i))))
+ ((and (>= p-org 0) (= (nth i p-list) p-org))
+ (setq pos-org (+ 2 (* 2 i))))
+ ((and (>= p-sta 0) (= (nth i p-list) p-sta))
+ (setq pos-sta (+ 2 (* 2 i))))
+ ((and (>= p-sum 0) (= (nth i p-list) p-sum))
+ (setq pos-sum (+ 2 (* 2 i))))
+ ((and (>= p-url 0) (= (nth i p-list) p-url))
+ (setq pos-url (+ 2 (* 2 i))))))
+ (mapc (lambda (ij)
+ (setq s (icalendar--rris (car ij) (cadr ij) s t t)))
+ (list
+ ;; summary must be first! because of %s
+ (list "%s"
+ (concat "\\(" icalendar-import-format-summary "\\)?"))
+ (list "%c"
+ (concat "\\(" icalendar-import-format-class "\\)?"))
+ (list "%d"
+ (concat "\\(" icalendar-import-format-description "\\)?"))
+ (list "%l"
+ (concat "\\(" icalendar-import-format-location "\\)?"))
+ (list "%o"
+ (concat "\\(" icalendar-import-format-organizer "\\)?"))
+ (list "%t"
+ (concat "\\(" icalendar-import-format-status "\\)?"))
+ (list "%u"
+ (concat "\\(" icalendar-import-format-url "\\)?"))))
+ (setq s (concat (icalendar--rris "%s" "\\(.*\\)" s nil t) " "))
+ (if (string-match s summary-and-rest)
+ (let (cla des loc org sta sum url)
+ (if (and pos-sum (match-beginning pos-sum))
+ (setq sum (substring summary-and-rest
+ (match-beginning pos-sum)
+ (match-end pos-sum))))
+ (if (and pos-cla (match-beginning pos-cla))
+ (setq cla (substring summary-and-rest
+ (match-beginning pos-cla)
+ (match-end pos-cla))))
+ (if (and pos-des (match-beginning pos-des))
+ (setq des (substring summary-and-rest
+ (match-beginning pos-des)
+ (match-end pos-des))))
+ (if (and pos-loc (match-beginning pos-loc))
+ (setq loc (substring summary-and-rest
+ (match-beginning pos-loc)
+ (match-end pos-loc))))
+ (if (and pos-org (match-beginning pos-org))
+ (setq org (substring summary-and-rest
+ (match-beginning pos-org)
+ (match-end pos-org))))
+ (if (and pos-sta (match-beginning pos-sta))
+ (setq sta (substring summary-and-rest
+ (match-beginning pos-sta)
+ (match-end pos-sta))))
+ (if (and pos-url (match-beginning pos-url))
+ (setq url (substring summary-and-rest
+ (match-beginning pos-url)
+ (match-end pos-url))))
+ (list (if cla (cons 'cla cla) nil)
+ (if des (cons 'des des) nil)
+ (if loc (cons 'loc loc) nil)
+ (if org (cons 'org org) nil)
+ (if sta (cons 'sta sta) nil)
+ ;;(if sum (cons 'sum sum) nil)
+ (if url (cons 'url url) nil)))))))
+
+;; subroutines for icalendar-export-region
+(defun icalendar--convert-ordinary-to-ical (nonmarker entry-main)
+ "Convert \"ordinary\" diary entry to icalendar format.
+NONMARKER is a regular expression matching the start of non-marking
+entries. ENTRY-MAIN is the first line of the diary entry."
+ (if (string-match (concat nonmarker
+ "\\([^ /]+[ /]+[^ /]+[ /]+[^ ]+\\)\\s-*"
+ "\\(0?\\([1-9][0-9]?:[0-9][0-9]\\)\\([ap]m\\)?"
+ "\\("
+ "-0?\\([1-9][0-9]?:[0-9][0-9]\\)\\([ap]m\\)?\\)?"
+ "\\)?"
+ "\\s-*\\(.*?\\) ?$")
+ entry-main)
+ (let* ((datetime (substring entry-main (match-beginning 1)
+ (match-end 1)))
+ (startisostring (icalendar--datestring-to-isodate
+ datetime))
+ (endisostring (icalendar--datestring-to-isodate
+ datetime 1))
+ (starttimestring (icalendar--diarytime-to-isotime
+ (if (match-beginning 3)
+ (substring entry-main
+ (match-beginning 3)
+ (match-end 3))
+ nil)
+ (if (match-beginning 4)
+ (substring entry-main
+ (match-beginning 4)
+ (match-end 4))
+ nil)))
+ (endtimestring (icalendar--diarytime-to-isotime
+ (if (match-beginning 6)
+ (substring entry-main
+ (match-beginning 6)
+ (match-end 6))
+ nil)
+ (if (match-beginning 7)
+ (substring entry-main
+ (match-beginning 7)
+ (match-end 7))
+ nil)))
+ (summary (icalendar--convert-string-for-export
+ (substring entry-main (match-beginning 8)
+ (match-end 8)))))
+ (icalendar--dmsg "ordinary %s" entry-main)
+
+ (unless startisostring
+ (error "Could not parse date"))
+ (when starttimestring
+ (unless endtimestring
+ (let ((time
+ (read (icalendar--rris "^T0?" ""
+ starttimestring))))
+ (setq endtimestring (format "T%06d"
+ (+ 10000 time))))))
+ (list (concat "\nDTSTART;"
+ (if starttimestring "VALUE=DATE-TIME:"
+ "VALUE=DATE:")
+ startisostring
+ (or starttimestring "")
+ "\nDTEND;"
+ (if endtimestring "VALUE=DATE-TIME:"
+ "VALUE=DATE:")
+ (if starttimestring
+ startisostring
+ endisostring)
+ (or endtimestring ""))
+ summary))
+ ;; no match
+ nil))
+
+(defun icalendar--convert-weekly-to-ical (nonmarker entry-main)
+ "Convert weekly diary entry to icalendar format.
+NONMARKER is a regular expression matching the start of non-marking
+entries. ENTRY-MAIN is the first line of the diary entry."
+ (if (and (string-match (concat nonmarker
+ "\\([a-z]+\\)\\s-+"
+ "\\(0?\\([1-9][0-9]?:[0-9][0-9]\\)"
+ "\\([ap]m\\)?"
+ "\\(-0?"
+ "\\([1-9][0-9]?:[0-9][0-9]\\)"
+ "\\([ap]m\\)?\\)?"
+ "\\)?"
+ "\\s-*\\(.*?\\) ?$")
+ entry-main)
+ (icalendar--get-weekday-abbrev
+ (substring entry-main (match-beginning 1)
+ (match-end 1))))
+ (let* ((day (icalendar--get-weekday-abbrev
+ (substring entry-main (match-beginning 1)
+ (match-end 1))))
+ (starttimestring (icalendar--diarytime-to-isotime
+ (if (match-beginning 3)
+ (substring entry-main
+ (match-beginning 3)
+ (match-end 3))
+ nil)
+ (if (match-beginning 4)
+ (substring entry-main
+ (match-beginning 4)
+ (match-end 4))
+ nil)))
+ (endtimestring (icalendar--diarytime-to-isotime
+ (if (match-beginning 6)
+ (substring entry-main
+ (match-beginning 6)
+ (match-end 6))
+ nil)
+ (if (match-beginning 7)
+ (substring entry-main
+ (match-beginning 7)
+ (match-end 7))
+ nil)))
+ (summary (icalendar--convert-string-for-export
+ (substring entry-main (match-beginning 8)
+ (match-end 8)))))
+ (icalendar--dmsg "weekly %s" entry-main)
+
+ (when starttimestring
+ (unless endtimestring
+ (let ((time (read
+ (icalendar--rris "^T0?" ""
+ starttimestring))))
+ (setq endtimestring (format "T%06d"
+ (+ 10000 time))))))
+ (list (concat "\nDTSTART;"
+ (if starttimestring
+ "VALUE=DATE-TIME:"
+ "VALUE=DATE:")
+ ;; find the correct week day,
+ ;; 1st january 2000 was a saturday
+ (format
+ "200001%02d"
+ (+ (icalendar--get-weekday-number day) 2))
+ (or starttimestring "")
+ "\nDTEND;"
+ (if endtimestring
+ "VALUE=DATE-TIME:"
+ "VALUE=DATE:")
+ (format
+ "200001%02d"
+ ;; end is non-inclusive!
+ (+ (icalendar--get-weekday-number day)
+ (if endtimestring 2 3)))
+ (or endtimestring "")
+ "\nRRULE:FREQ=WEEKLY;INTERVAL=1;BYDAY="
+ day)
+ summary))
+ ;; no match
+ nil))
+
+(defun icalendar--convert-yearly-to-ical (nonmarker entry-main)
+ "Convert yearly diary entry to icalendar format.
+NONMARKER is a regular expression matching the start of non-marking
+entries. ENTRY-MAIN is the first line of the diary entry."
+ (if (string-match (concat nonmarker
+ (if european-calendar-style
+ "0?\\([1-9]+[0-9]?\\)\\s-+\\([a-z]+\\)\\s-+"
+ "\\([a-z]+\\)\\s-+0?\\([1-9]+[0-9]?\\)\\s-+")
+ "\\*?\\s-*"
+ "\\(0?\\([1-9][0-9]?:[0-9][0-9]\\)\\([ap]m\\)?"
+ "\\("
+ "-0?\\([1-9][0-9]?:[0-9][0-9]\\)\\([ap]m\\)?\\)?"
+ "\\)?"
+ "\\s-*\\([^0-9]+.*?\\) ?$" ; must not match years
+ )
+ entry-main)
+ (let* ((daypos (if european-calendar-style 1 2))
+ (monpos (if european-calendar-style 2 1))
+ (day (read (substring entry-main
+ (match-beginning daypos)
+ (match-end daypos))))
+ (month (icalendar--get-month-number
+ (substring entry-main
+ (match-beginning monpos)
+ (match-end monpos))))
+ (starttimestring (icalendar--diarytime-to-isotime
+ (if (match-beginning 4)
+ (substring entry-main
+ (match-beginning 4)
+ (match-end 4))
+ nil)
+ (if (match-beginning 5)
+ (substring entry-main
+ (match-beginning 5)
+ (match-end 5))
+ nil)))
+ (endtimestring (icalendar--diarytime-to-isotime
+ (if (match-beginning 7)
+ (substring entry-main
+ (match-beginning 7)
+ (match-end 7))
+ nil)
+ (if (match-beginning 8)
+ (substring entry-main
+ (match-beginning 8)
+ (match-end 8))
+ nil)))
+ (summary (icalendar--convert-string-for-export
+ (substring entry-main (match-beginning 9)
+ (match-end 9)))))
+ (icalendar--dmsg "yearly %s" entry-main)
+
+ (when starttimestring
+ (unless endtimestring
+ (let ((time (read
+ (icalendar--rris "^T0?" ""
+ starttimestring))))
+ (setq endtimestring (format "T%06d"
+ (+ 10000 time))))))
+ (list (concat "\nDTSTART;"
+ (if starttimestring "VALUE=DATE-TIME:"
+ "VALUE=DATE:")
+ (format "1900%02d%02d" month day)
+ (or starttimestring "")
+ "\nDTEND;"
+ (if endtimestring "VALUE=DATE-TIME:"
+ "VALUE=DATE:")
+ ;; end is not included! shift by one day
+ (icalendar--date-to-isodate
+ (list month day 1900)
+ (if endtimestring 0 1))
+ (or endtimestring "")
+ "\nRRULE:FREQ=YEARLY;INTERVAL=1;BYMONTH="
+ (format "%2d" month)
+ ";BYMONTHDAY="
+ (format "%2d" day))
+ summary))
+ ;; no match
+ nil))
+
+(defun icalendar--convert-sexp-to-ical (nonmarker entry-main)
+ "Convert complex sexp diary entry to icalendar format -- unsupported!
+
+FIXME!
+
+NONMARKER is a regular expression matching the start of non-marking
+entries. ENTRY-MAIN is the first line of the diary entry."
+ (cond ((string-match (concat nonmarker
+ "%%(and \\(([^)]+)\\))\\(\\s-*.*?\\) ?$")
+ entry-main)
+ ;; simple sexp entry as generated by icalendar.el: strip off the
+ ;; unnecessary (and)
+ (icalendar--dmsg "diary-sexp from icalendar.el %s" entry-main)
+ (icalendar--convert-to-ical
+ nonmarker
+ (concat "%%"
+ (substring entry-main (match-beginning 1) (match-end 1))
+ (substring entry-main (match-beginning 2) (match-end 2)))))
+ ((string-match (concat nonmarker
+ "%%([^)]+)\\s-*.*")
+ entry-main)
+ (icalendar--dmsg "diary-sexp %s" entry-main)
+ (error "Sexp-entries are not supported yet"))
+ (t
+ ;; no match
+ nil)))
+
+(defun icalendar--convert-block-to-ical (nonmarker entry-main)
+ "Convert block diary entry to icalendar format.
+NONMARKER is a regular expression matching the start of non-marking
+entries. ENTRY-MAIN is the first line of the diary entry."
+ (if (string-match (concat nonmarker
+ "%%(diary-block \\([^ /]+[ /]+[^ /]+[ /]+[^ ]+\\)"
+ " +\\([^ /]+[ /]+[^ /]+[ /]+[^ ]+\\))\\s-*"
+ "\\(0?\\([1-9][0-9]?:[0-9][0-9]\\)\\([ap]m\\)?"
+ "\\("
+ "-0?\\([1-9][0-9]?:[0-9][0-9]\\)\\([ap]m\\)?\\)?"
+ "\\)?"
+ "\\s-*\\(.*?\\) ?$")
+ entry-main)
+ (let* ((startstring (substring entry-main
+ (match-beginning 1)
+ (match-end 1)))
+ (endstring (substring entry-main
+ (match-beginning 2)
+ (match-end 2)))
+ (startisostring (icalendar--datestring-to-isodate
+ startstring))
+ (endisostring (icalendar--datestring-to-isodate
+ endstring))
+ (endisostring+1 (icalendar--datestring-to-isodate
+ endstring 1))
+ (starttimestring (icalendar--diarytime-to-isotime
+ (if (match-beginning 4)
+ (substring entry-main
+ (match-beginning 4)
+ (match-end 4))
+ nil)
+ (if (match-beginning 5)
+ (substring entry-main
+ (match-beginning 5)
+ (match-end 5))
+ nil)))
+ (endtimestring (icalendar--diarytime-to-isotime
+ (if (match-beginning 7)
+ (substring entry-main
+ (match-beginning 7)
+ (match-end 7))
+ nil)
+ (if (match-beginning 8)
+ (substring entry-main
+ (match-beginning 8)
+ (match-end 8))
+ nil)))
+ (summary (icalendar--convert-string-for-export
+ (substring entry-main (match-beginning 9)
+ (match-end 9)))))
+ (icalendar--dmsg "diary-block %s" entry-main)
+ (when starttimestring
+ (unless endtimestring
+ (let ((time
+ (read (icalendar--rris "^T0?" ""
+ starttimestring))))
+ (setq endtimestring (format "T%06d"
+ (+ 10000 time))))))
+ (if starttimestring
+ ;; with time -> write rrule
+ (list (concat "\nDTSTART;VALUE=DATE-TIME:"
+ startisostring
+ starttimestring
+ "\nDTEND;VALUE=DATE-TIME:"
+ startisostring
+ endtimestring
+ "\nRRULE:FREQ=DAILY;INTERVAL=1;UNTIL="
+ endisostring)
+ summary)
+ ;; no time -> write long event
+ (list (concat "\nDTSTART;VALUE=DATE:" startisostring
+ "\nDTEND;VALUE=DATE:" endisostring+1)
+ summary)))
+ ;; no match
+ nil))
+
+(defun icalendar--convert-float-to-ical (nonmarker entry-main)
+ "Convert float diary entry to icalendar format -- unsupported!
+
+FIXME!
+
+NONMARKER is a regular expression matching the start of non-marking
+entries. ENTRY-MAIN is the first line of the diary entry."
+ (if (string-match (concat nonmarker
+ "%%(diary-float \\([^)]+\\))\\s-*\\(.*?\\) ?$")
+ entry-main)
+ (progn
+ (icalendar--dmsg "diary-float %s" entry-main)
+ (error "`diary-float' is not supported yet"))
+ ;; no match
+ nil))
+
+(defun icalendar--convert-date-to-ical (nonmarker entry-main)
+ "Convert `diary-date' diary entry to icalendar format -- unsupported!
+
+FIXME!
+
+NONMARKER is a regular expression matching the start of non-marking
+entries. ENTRY-MAIN is the first line of the diary entry."
+ (if (string-match (concat nonmarker
+ "%%(diary-date \\([^)]+\\))\\s-*\\(.*?\\) ?$")
+ entry-main)
+ (progn
+ (icalendar--dmsg "diary-date %s" entry-main)
+ (error "`diary-date' is not supported yet"))
+ ;; no match
+ nil))
+
+(defun icalendar--convert-cyclic-to-ical (nonmarker entry-main)
+ "Convert `diary-cyclic' diary entry to icalendar format.
+NONMARKER is a regular expression matching the start of non-marking
+entries. ENTRY-MAIN is the first line of the diary entry."
+ (if (string-match (concat nonmarker
+ "%%(diary-cyclic \\([^ ]+\\) +"
+ "\\([^ /]+[ /]+[^ /]+[ /]+[^ ]+\\))\\s-*"
+ "\\(0?\\([1-9][0-9]?:[0-9][0-9]\\)\\([ap]m\\)?"
+ "\\("
+ "-0?\\([1-9][0-9]?:[0-9][0-9]\\)\\([ap]m\\)?\\)?"
+ "\\)?"
+ "\\s-*\\(.*?\\) ?$")
+ entry-main)
+ (let* ((frequency (substring entry-main (match-beginning 1)
+ (match-end 1)))
+ (datetime (substring entry-main (match-beginning 2)
+ (match-end 2)))
+ (startisostring (icalendar--datestring-to-isodate
+ datetime))
+ (endisostring (icalendar--datestring-to-isodate
+ datetime))
+ (endisostring+1 (icalendar--datestring-to-isodate
+ datetime 1))
+ (starttimestring (icalendar--diarytime-to-isotime
+ (if (match-beginning 4)
+ (substring entry-main
+ (match-beginning 4)
+ (match-end 4))
+ nil)
+ (if (match-beginning 5)
+ (substring entry-main
+ (match-beginning 5)
+ (match-end 5))
+ nil)))
+ (endtimestring (icalendar--diarytime-to-isotime
+ (if (match-beginning 7)
+ (substring entry-main
+ (match-beginning 7)
+ (match-end 7))
+ nil)
+ (if (match-beginning 8)
+ (substring entry-main
+ (match-beginning 8)
+ (match-end 8))
+ nil)))
+ (summary (icalendar--convert-string-for-export
+ (substring entry-main (match-beginning 9)
+ (match-end 9)))))
+ (icalendar--dmsg "diary-cyclic %s" entry-main)
+ (when starttimestring
+ (unless endtimestring
+ (let ((time
+ (read (icalendar--rris "^T0?" ""
+ starttimestring))))
+ (setq endtimestring (format "T%06d"
+ (+ 10000 time))))))
+ (list (concat "\nDTSTART;"
+ (if starttimestring "VALUE=DATE-TIME:"
+ "VALUE=DATE:")
+ startisostring
+ (or starttimestring "")
+ "\nDTEND;"
+ (if endtimestring "VALUE=DATE-TIME:"
+ "VALUE=DATE:")
+ (if endtimestring endisostring endisostring+1)
+ (or endtimestring "")
+ "\nRRULE:FREQ=DAILY;INTERVAL=" frequency
+ ;; strange: korganizer does not expect
+ ;; BYSOMETHING here...
+ )
+ summary))
+ ;; no match
+ nil))
+
+(defun icalendar--convert-anniversary-to-ical (nonmarker entry-main)
+ "Convert `diary-anniversary' diary entry to icalendar format.
+NONMARKER is a regular expression matching the start of non-marking
+entries. ENTRY-MAIN is the first line of the diary entry."
+ (if (string-match (concat nonmarker
+ "%%(diary-anniversary \\([^)]+\\))\\s-*"
+ "\\(0?\\([1-9][0-9]?:[0-9][0-9]\\)\\([ap]m\\)?"
+ "\\("
+ "-0?\\([1-9][0-9]?:[0-9][0-9]\\)\\([ap]m\\)?\\)?"
+ "\\)?"
+ "\\s-*\\(.*?\\) ?$")
+ entry-main)
+ (let* ((datetime (substring entry-main (match-beginning 1)
+ (match-end 1)))
+ (startisostring (icalendar--datestring-to-isodate
+ datetime))
+ (endisostring (icalendar--datestring-to-isodate
+ datetime 1))
+ (starttimestring (icalendar--diarytime-to-isotime
+ (if (match-beginning 3)
+ (substring entry-main
+ (match-beginning 3)
+ (match-end 3))
+ nil)
+ (if (match-beginning 4)
+ (substring entry-main
+ (match-beginning 4)
+ (match-end 4))
+ nil)))
+ (endtimestring (icalendar--diarytime-to-isotime
+ (if (match-beginning 6)
+ (substring entry-main
+ (match-beginning 6)
+ (match-end 6))
+ nil)
+ (if (match-beginning 7)
+ (substring entry-main
+ (match-beginning 7)
+ (match-end 7))
+ nil)))
+ (summary (icalendar--convert-string-for-export
+ (substring entry-main (match-beginning 8)
+ (match-end 8)))))
+ (icalendar--dmsg "diary-anniversary %s" entry-main)
+ (when starttimestring
+ (unless endtimestring
+ (let ((time
+ (read (icalendar--rris "^T0?" ""
+ starttimestring))))
+ (setq endtimestring (format "T%06d"
+ (+ 10000 time))))))
+ (list (concat "\nDTSTART;"
+ (if starttimestring "VALUE=DATE-TIME:"
+ "VALUE=DATE:")
+ startisostring
+ (or starttimestring "")
+ "\nDTEND;"
+ (if endtimestring "VALUE=DATE-TIME:"
+ "VALUE=DATE:")
+ endisostring
+ (or endtimestring "")
+ "\nRRULE:FREQ=YEARLY;INTERVAL=1"
+ ;; the following is redundant,
+ ;; but korganizer seems to expect this... ;(
+ ;; and evolution doesn't understand it... :(
+ ;; so... who is wrong?!
+ ";BYMONTH="
+ (substring startisostring 4 6)
+ ";BYMONTHDAY="
+ (substring startisostring 6 8))
+ summary))
+ ;; no match
+ nil))
+