(end (gnus-icalendar-event:end-time event))
(start-date (format-time-string "%Y-%m-%d %a" start))
(start-time (format-time-string "%H:%M" start))
+ (start-at-midnight (string= start-time "00:00"))
(end-date (format-time-string "%Y-%m-%d %a" end))
(end-time (format-time-string "%H:%M" end))
+ (end-at-midnight (string= end-time "00:00"))
+ (start-end-date-diff (/ (float-time (time-subtract
+ (date-to-time end-date)
+ (date-to-time start-date)))
+ 86400))
(org-repeat (gnus-icalendar-event:org-repeat event))
- (repeat (if org-repeat (concat " " org-repeat) "")))
-
- (if (equal start-date end-date)
- (format "<%s %s-%s%s>" start-date start-time end-time repeat)
- (format "<%s %s>--<%s %s>" start-date start-time end-date end-time))))
+ (repeat (if org-repeat (concat " " org-repeat) ""))
+ (time-1-day '(0 86400)))
+
+ ;; NOTE: special care is needed with appointments ending at midnight
+ ;; (typically all-day events): the end time has to be changed to 23:59 to
+ ;; prevent org agenda showing the event on one additional day
+ (cond
+ ;; start/end midnight
+ ;; A 0:0 - A+1 0:0 -> A
+ ;; A 0:0 - A+n 0:0 -> A - A+n-1
+ ((and start-at-midnight end-at-midnight) (if (> start-end-date-diff 1)
+ (let ((end-ts (format-time-string "%Y-%m-%d %a" (time-subtract end time-1-day))))
+ (format "<%s>--<%s>" start-date end-ts))
+ (format "<%s%s>" start-date repeat)))
+ ;; end midnight
+ ;; A .:. - A+1 0:0 -> A .:.-23:59
+ ;; A .:. - A+n 0:0 -> A .:. - A_n-1
+ (end-at-midnight (if (= start-end-date-diff 1)
+ (format "<%s %s-23:59%s>" start-date start-time repeat)
+ (let ((end-ts (format-time-string "%Y-%m-%d %a" (time-subtract end time-1-day))))
+ (format "<%s %s>--<%s>" start-date start-time end-ts))))
+ ;; start midnight
+ ;; A 0:0 - A .:. -> A 0:0-.:. (default 1)
+ ;; A 0:0 - A+n .:. -> A - A+n .:.
+ ((and start-at-midnight
+ (plusp start-end-date-diff)) (format "<%s>--<%s %s>" start-date end-date end-time))
+ ;; default
+ ;; A .:. - A .:. -> A .:.-.:.
+ ;; A .:. - B .:.
+ ((zerop start-end-date-diff) (format "<%s %s-%s%s>" start-date start-time end-time repeat))
+ (t (format "<%s %s>--<%s %s>" start-date start-time end-date end-time)))))
(defun gnus-icalendar--format-summary-line (summary &optional location)
(if location
:type '(string)
:group 'gnus-icalendar)
+(defcustom gnus-icalendar-additional-identities nil
+ "We need to know your identity to make replies to calendar requests work.
+
+Gnus will only offer you the Accept/Tentative/Decline buttons for
+calendar events if any of your identities matches at least one
+RSVP participant.
+
+Your identity is guessed automatically from the variables `user-full-name',
+`user-mail-address', and `gnus-ignored-from-addresses'.
+
+If you need even more aliases you can define them here. It really
+only makes sense to define names or email addresses."
+
+ :type '(repeat string)
+ :group 'gnus-icalendar)
+
(make-variable-buffer-local
(defvar gnus-icalendar-reply-status nil))
(apply #'append
(mapcar (lambda (x) (if (listp x) x (list x)))
(list user-full-name (regexp-quote user-mail-address)
- ; NOTE: this one can be a list
- gnus-ignored-from-addresses))))
+ ; NOTE: these can be lists
+ gnus-ignored-from-addresses ; already regexp-quoted
+ (mapcar #'regexp-quote gnus-icalendar-additional-identities)))))
;; TODO: make the template customizable
(defmethod gnus-icalendar-event->gnus-calendar ((event gnus-icalendar-event) &optional reply-status)