Here's a possible implementation. It is based on the idea of adding the actual deadline time stamp as a property to the heading (do C-h i g(org)properties and columns
to read about properties in Org mode). So the Org mode file would look like this:
#+CATEGORY: Math 1234
* TODO Assignment
DEADLINE: <2021-11-14 Sun 10:00> (Time I want to finish the assignment)
:PROPERTIES:
:ActualDeadline: <2021-11-15 Mon 10:00>
:END:
Adding it as a property allows easy retrieval of it later using the Propery API (see C-h i g(org)Using the Property API
). With point
anywhere in a heading, all you have to do is:
(org-entry-get nil "ActualDeadline")
In the heading above, you get the string "<2021-11-15 Mon 10:00>"
as the value. If there is no such property, you get nil
.
The next step is to define a function that looks for an ActualDeadline
property in the current heading and if it finds one, it compares the date from the timestamp with the agenda date: if the dates are equal, then the function returns the string "Actual Deadline ", otherwise it returns an empty string:
(defun actual-deadline ()
(let ((ts (org-entry-get nil "ActualDeadline"))
tsdate)
(setq tsdate (if ts
(calendar-gregorian-from-absolute
(time-to-days (org-read-date nil t ts nil)))
nil))
(if (and tsdate (equal org-agenda-current-date tsdate))
;; there was an ActualDeadline property and the dates agree
"Actual Deadline: "
""))
The hardest part here is to convert the date from the timestamp into the (month day year)
format that the calendar uses. That is necessary because org-agenda-current-date
, the variable that remembers the current date while processing each day's items in the agenda, uses that format. Note that if there is no ActualDeadline
property or if the dates do not agree, the function returns the empty string.
Now all you have to do is redefine the agenda entry in org-agenda-prefix-format
to use the above function. There is a %(expr)
format that allows you to evaluate an arbitrary lisp expression: the format is replaced by the (string) value of the expression - see the doc string of the variable with C-h v org-agenda-prefix-format
for the details. In particular, we can have it call the function above:
(setf (cdr (assq 'agenda org-agenda-prefix-format))
" %i %-12:c%?-12t%(actual-deadline)% s")
That's the default value of the format for the agenda, except that I've interpolated the call to the function: %(actual-deadline)
.
You can add the function to your init file, but you have to be careful when you add the setting of org-agenda-prefix-format
: the code above assumes that the variable is already defined, but the variable is only defined after org-agenda
is loaded, so the safest thing to do is to use with-eval-after-load
:
(with eval-after-load 'org-agenda
(setf (cdr (assq 'agenda org-agenda-prefix-format))
" %i %-12:c%?-12t%(actual-deadline)% s")
Here's how it looks:
Sunday 14 November 2021
Weather: 6:30...... Sunrise
Math 1234: 10:00...... Deadline: TODO Assignment
Weather: 16:26...... Sunset
Monday 15 November 2021 W46
Weather: 6:32...... Sunrise
Math 1234: 10:00...... Actual Deadline: TODO Assignment
Weather: 16:26...... Sunset
EDIT: Adding a property to an Org mode heading is easy. There is a convenient keybinding for it: C-c C-x p
bound to org-set-property
. It asks you for the name of the property and it allows for completion, so that is easy to do. It then asks for the value of the property and that's a problem: you would like the value of the ActualDeadline
problem to be an active timestamp, but the keybinding C-c .
that is normally used for that is only available in an Org mode buffer, not in the minibuffer where org-set-property
is asking you to enter it. You can enter it by hand of course, but it might be convenient to make org-time-stamp
available through a keybinding in the minibuffer. Fortunately, the C-c .
key is generally not defined in the minibuffer, so you can add it for yourself:
(define-key minibuffer-mode-map (kbd "C-c .") #'org-time-stamp)
That gives you the standard Org mode method of adding a time stamp in the minibuffer, so adding an ActualDeadline property with a time stamp value becomes pretty easy:
C-c C-x p Ac TAB RET C-c . ... RET
i.e. call org-set-property, start giving it the name of the property, TAB for completion, RET to accept (assuming there is no other property starting with Ac
) then C-c .
to start the dialog for a time stamp, then RET when you are done. That's easier done than said.