Function: icalendar--convert-recurring-to-diary

icalendar--convert-recurring-to-diary is a byte-compiled function defined in icalendar.el.gz.

Signature

(icalendar--convert-recurring-to-diary E DTSTART-DEC START-T END-T)

Documentation

Convert recurring iCalendar event E to diary format.

DTSTART-DEC is the DTSTART property of E. START-T is the event's start time in diary format. END-T is the event's end time in diary format.

Source Code

;; Defined in /usr/src/emacs/lisp/calendar/icalendar.el.gz
;; subroutines for importing
(defun icalendar--convert-recurring-to-diary (e dtstart-dec start-t end-t)
  "Convert recurring iCalendar event E to diary format.

DTSTART-DEC is the DTSTART property of E.
START-T is the event's start time in diary format.
END-T is the event's end time in diary format."
  (icalendar--dmsg "recurring event")
  (let* ((rrule        (icalendar--get-event-property e 'RRULE))
         (rrule-props  (icalendar--split-value rrule))
         (frequency    (cadr (assoc 'FREQ rrule-props)))
         (until        (cadr (assoc 'UNTIL rrule-props)))
         (count        (cadr (assoc 'COUNT rrule-props)))
         (interval     (read (or (cadr (assoc 'INTERVAL rrule-props)) "1")))
         (dtstart-conv (icalendar--datetime-to-diary-date dtstart-dec))
         (until-conv   (icalendar--datetime-to-diary-date
                        (icalendar--decode-isodatetime until)))
         (until-1-conv (icalendar--datetime-to-diary-date
                        (icalendar--decode-isodatetime until -1)))
         (result  ""))

    ;; FIXME FIXME interval!!!!!!!!!!!!!

    (when count
      (if until
          (message "Must not have UNTIL and COUNT -- ignoring COUNT element!")
        (let ((until-1 0))
          (cond ((string-equal frequency "DAILY")
                 (setq until (icalendar--add-decoded-times
                              dtstart-dec
                              (list 0 0 0 (* (read count) interval) 0 0)))
                 (setq until-1 (icalendar--add-decoded-times
                                dtstart-dec
                                (list 0 0 0 (* (- (read count) 1) interval)
                                      0 0)))
                 )
                ((string-equal frequency "WEEKLY")
                 (setq until (icalendar--add-decoded-times
                              dtstart-dec
                              (list 0 0 0 (* (read count) 7 interval) 0 0)))
                 (setq until-1 (icalendar--add-decoded-times
                                dtstart-dec
                                (list 0 0 0 (* (- (read count) 1) 7
                                               interval) 0 0)))
                 )
                ((string-equal frequency "MONTHLY")
                 (setq until (icalendar--add-decoded-times
                              dtstart-dec (list 0 0 0 0 (* (- (read count) 1)
                                                           interval) 0)))
                 (setq until-1 (icalendar--add-decoded-times
                                dtstart-dec (list 0 0 0 0 (* (- (read count) 1)
                                                             interval) 0)))
                 )
                ((string-equal frequency "YEARLY")
                 (setq until (icalendar--add-decoded-times
                              dtstart-dec (list 0 0 0 0 0 (* (- (read count) 1)
                                                             interval))))
                 (setq until-1 (icalendar--add-decoded-times
                                dtstart-dec
                                (list 0 0 0 0 0 (* (- (read count) 1)
                                                   interval))))
                 )
                (t
                 (message "Cannot handle COUNT attribute for `%s' events."
                          frequency)))
          (setq until-conv (icalendar--datetime-to-diary-date until))
          (setq until-1-conv (icalendar--datetime-to-diary-date until-1))
          ))
      )
    (cond ((string-equal frequency "WEEKLY")
	   (let* ((byday (cadr (assoc 'BYDAY rrule-props)))
		  (weekdays
		   (icalendar--get-weekday-numbers byday))
		  (weekday-clause
		   (when (> (length weekdays) 1)
		     (format "(memq (calendar-day-of-week date) '%s) "
			     weekdays))))
	     (if (not start-t)
		 (progn
		   ;; weekly and all-day
		   (icalendar--dmsg "weekly all-day")
		   (if until
		       (setq result
			     (format
			      (concat "%%%%(and "
				      "%s"
				      "(diary-block %s %s))")
			      (or weekday-clause
				  (format "(diary-cyclic %d %s) "
					  (* interval 7)
					  dtstart-conv))
			      dtstart-conv
			      (if count until-1-conv until-conv)
			      ))
		       (setq result
			     (format "%%%%(and %s(diary-cyclic %d %s))"
				     (or weekday-clause "")
				     (if weekday-clause 1 (* interval 7))
				     dtstart-conv))))
               ;; weekly and not all-day
               (icalendar--dmsg "weekly not-all-day")
               (if until
                   (setq result
                         (format
                          (concat "%%%%(and "
                                  "%s"
                                  "(diary-block %s %s)) "
                                  "%s%s%s")
			  (or weekday-clause
			      (format "(diary-cyclic %d %s) "
				      (* interval 7)
				      dtstart-conv))
                          dtstart-conv
                          until-conv
                          (or start-t "")
                          (if end-t "-" "") (or end-t "")))
                 ;; no limit
                 ;; FIXME!!!!
                 ;; DTSTART;VALUE=DATE-TIME:20030919T090000
                 ;; DTEND;VALUE=DATE-TIME:20030919T113000
                 (setq result
                       (format
                        "%%%%(and %s(diary-cyclic %d %s)) %s%s%s"
			(or weekday-clause "")
			(if weekday-clause 1 (* interval 7))
			dtstart-conv
			(or start-t "")
                        (if end-t "-" "") (or end-t "")))))))
          ;; yearly
          ((string-equal frequency "YEARLY")
           (icalendar--dmsg "yearly")
           (if until
               (let ((day (nth 3 dtstart-dec))
                     (month (nth 4 dtstart-dec)))
                 (setq result (concat "%%(and (diary-date "
                                      (cond ((eq calendar-date-style 'iso)
                                             (format "t %d %d" month day))
                                            ((eq calendar-date-style 'european)
                                             (format "%d %d t" day month))
                                            ((eq calendar-date-style 'american)
                                             (format "%d %d t" month day)))
                                      ") (diary-block "
                                      dtstart-conv
                                      " "
                                      until-conv
                                      ")) "
                                      (or start-t "")
                                      (if end-t "-" "")
                                      (or end-t ""))))
             (setq result (format
                           "%%%%(diary-anniversary %s) %s%s%s"
                           (let* ((year (nth 5 dtstart-dec))
                                  (dtstart-1y-dec (copy-sequence dtstart-dec)))
                             (setf (nth 5 dtstart-1y-dec) (1- year))
                             (icalendar--datetime-to-diary-date dtstart-1y-dec))
                           (or start-t "")
                           (if end-t "-" "") (or end-t "")))))
          ;; monthly
          ((string-equal frequency "MONTHLY")
           (icalendar--dmsg "monthly")
	   (let* ((byday (cadr (assoc 'BYDAY rrule-props)))
                  (count-weekday
                   (and byday
                        (save-match-data
                          (when (string-match "\\(-?[0-9]+\\)\\([A-Z][A-Z]\\)"
                                              byday)
                            (cons (substring byday
                                             (match-beginning 1)
                                             (match-end 1))
                                  (substring byday
                                             (match-beginning 2)
                                             (match-end 2)))))))
                  (rule-part
                   (if count-weekday
                       (let ((count (car count-weekday))
                             (weekdaynum (icalendar--get-weekday-number
                                          (cdr count-weekday))))
                         ;; FIXME: this is valid only for interval==1
                         (format "(diary-float t %s %s)" weekdaynum count))
                     (format "(diary-date %s)"
                             (let ((day (nth 3 dtstart-dec)))
                               (cond ((eq calendar-date-style 'iso)
                                      (format "t t %d" day))
                                     ((eq calendar-date-style 'european)
                                      (format "%d t t" day))
                                     ((eq calendar-date-style 'american)
                                      (format "t %d t" day))))))))
             (setq result
                   (format
                    "%%%%(and %s (diary-block %s %s)) %s%s%s"
                    rule-part
                    dtstart-conv
                    (if until
                        until-conv
                      (if (eq calendar-date-style 'iso) "9999 1 1" "1 1 9999")) ;; FIXME: should be unlimited
                    (or start-t "")
                    (if end-t "-" "") (or end-t "")))))
          ;; daily
          ((and (string-equal frequency "DAILY"))
           (if until
               (setq result
                     (format
                      (concat "%%%%(and (diary-cyclic %s %s) "
                              "(diary-block %s %s)) %s%s%s")
                      interval dtstart-conv dtstart-conv
                      (if count until-1-conv until-conv)
                      (or start-t "")
                      (if end-t "-" "") (or end-t "")))
             (setq result
                   (format
                    "%%%%(and (diary-cyclic %s %s)) %s%s%s"
                    interval
                    dtstart-conv
                    (or start-t "")
                    (if end-t "-" "") (or end-t ""))))))
    ;; Handle exceptions from recurrence rules
    (let ((ex-dates (icalendar--get-event-properties e 'EXDATE)))
      (while ex-dates
        (let* ((ex-start (icalendar--decode-isodatetime
                          (car ex-dates)))
               (ex-d (icalendar--datetime-to-diary-date
                      ex-start)))
          (setq result
                (replace-regexp-in-string "^%%(\\(and \\)?"
                                 (format
                                  "%%%%(and (not (diary-date %s)) "
                                  ex-d)
                                 result)))
        (setq ex-dates (cdr ex-dates))))
    ;; FIXME: exception rules are not recognized
    (if (icalendar--get-event-property e 'EXRULE)
        (setq result
              (concat result
                      "\n Exception rules: "
                      (icalendar--get-event-properties
                       e 'EXRULE))))
    result))