Here's one way:
(defun to-integer-mins (s)
"Convert a string in HH:MM format to integer minutes."
(seq-reduce (lambda (x y) (+ y (* x 60)))
(mapcar #'string-to-number (split-string s ":")) 0)
(defun int-to-hh-mm (n)
"Convert an integer to an HH:MM format string."
(let* ((h (/ n 60))
(m (- n (* h 60))))
(format "%02d:%02d" h m)))
(org-entry-get (point) "Effort"))
(org-map-entries #'get-effort t 'tree))
If you do
ESC ESC : (get-total-effort) RET with point at the "test" headline, you will get
The main point here is the call to
(org-map-entries #'get-effort t 'tree)
which will traverse the subtree, apply the
get-effort function on each headline and accumulate the results in a list. The
get-effort function checks for an
Effort property and returns it if found (if not, it returns nil). If you run the above call to
org-map-entries at the top-level headline with
ESC ESC : (org-map-entries #'get-effort t 'tree) RET you will get:
(nil "0:07" "0:07")
the sequence of Effort values at each headline of the tree.
All you have to do now is add them all together, but that is a bit messier than it sounds: you have to convert the strings to numbers (the number of minutes for each one), add them together to get the total number of minutes and then convert the numeric result to a string in
HH:MM format. There are many ways to do that, but they have nothing to do with Org mode: they are generic data manipulations using standard emacs-lisp functions. I chose to implement them in functional style using
seq-reduce but they can be implemented using a more imperative style using loops instead.