Function: org-clock-sum

org-clock-sum is an autoloaded and byte-compiled function defined in org-clock.el.gz.

Signature

(org-clock-sum &optional TSTART TEND HEADLINE-FILTER PROPNAME)

Documentation

Sum the times for each subtree.

Puts the resulting times in minutes as a text property on each headline. TSTART and TEND can mark a time range to be considered. HEADLINE-FILTER is a zero-arg function that, if specified, is called for each headline in the time range with point at the headline. Headlines for which HEADLINE-FILTER returns nil are excluded from the clock summation. PROPNAME lets you set a custom text property instead of :org-clock-minutes.

Source Code

;; Defined in /usr/src/emacs/lisp/org/org-clock.el.gz
;;;###autoload
(defun org-clock-sum (&optional tstart tend headline-filter propname)
  "Sum the times for each subtree.
Puts the resulting times in minutes as a text property on each headline.
TSTART and TEND can mark a time range to be considered.
HEADLINE-FILTER is a zero-arg function that, if specified, is called for
each headline in the time range with point at the headline.  Headlines for
which HEADLINE-FILTER returns nil are excluded from the clock summation.
PROPNAME lets you set a custom text property instead of :org-clock-minutes."
  (with-silent-modifications
    (let* ((re (concat "^\\(\\*+\\)[ \t]\\|^[ \t]*"
		       org-clock-string
		       "[ \t]*\\(?:\\(\\[.*?\\]\\)-+\\(\\[.*?\\]\\)\\|=>[ \t]+\\([0-9]+\\):\\([0-9]+\\)\\)"))
	   (lmax 30)
	   (ltimes (make-vector lmax 0))
	   (level 0)
	   (tstart (cond ((stringp tstart) (org-time-string-to-seconds tstart))
			 ((consp tstart) (float-time tstart))
			 (t tstart)))
	   (tend (cond ((stringp tend) (org-time-string-to-seconds tend))
		       ((consp tend) (float-time tend))
		       (t tend)))
	   (t1 0)
	   time)
      (remove-text-properties (point-min) (point-max)
			      `(,(or propname :org-clock-minutes) t
				:org-clock-force-headline-inclusion t))
      (save-excursion
	(goto-char (point-max))
	(while (re-search-backward re nil t)
          (let* ((element (save-match-data (org-element-at-point)))
                 (element-type (org-element-type element)))
	    (cond
	     ((and (eq element-type 'clock) (match-end 2))
	      ;; Two time stamps.
              (condition-case nil
                  (let* ((timestamp (org-element-property :value element))
                         (ts (float-time
                              (org-encode-time
                               (list 0
                                     (org-element-property :minute-start timestamp)
                                     (org-element-property :hour-start timestamp)
                                     (org-element-property :day-start timestamp)
                                     (org-element-property :month-start timestamp)
                                     (org-element-property :year-start timestamp)
                                     nil -1 nil))))
                         (te (float-time
                              (org-encode-time
                               (list 0
                                     (org-element-property :minute-end timestamp)
                                     (org-element-property :hour-end timestamp)
                                     (org-element-property :day-end timestamp)
                                     (org-element-property :month-end timestamp)
                                     (org-element-property :year-end timestamp)
                                     nil -1 nil))))
                         (dt (- (if tend (min te tend) te)
                                (if tstart (max ts tstart) ts))))
                    (when (> dt 0) (cl-incf t1 (floor dt 60))))
                (error
                 (org-display-warning (format "org-clock-sum: Ignoring invalid %s" (org-current-line-string))))))
	     ((match-end 4)
	      ;; A naked time.
	      (setq t1 (+ t1 (string-to-number (match-string 5))
			  (* 60 (string-to-number (match-string 4))))))
	     ((memq element-type '(headline inlinetask)) ;A headline
	      ;; Add the currently clocking item time to the total.
	      (when (and org-clock-report-include-clocking-task
                         (eq (org-clocking-buffer) (current-buffer))
                         (eq (marker-position org-clock-hd-marker) (point))
                         tstart
                         tend
                         (>= (float-time org-clock-start-time) tstart)
                         (<= (float-time org-clock-start-time) tend))
                (let ((time (floor (org-time-convert-to-integer
				    (time-since org-clock-start-time))
				   60)))
		  (setq t1 (+ t1 time))))
	      (let* ((headline-forced
		      (get-text-property (point)
                                         :org-clock-force-headline-inclusion))
		     (headline-included
		      (or (null headline-filter)
			  (save-excursion
			    (save-match-data (funcall headline-filter))))))
                (setq level (- (match-end 1) (match-beginning 1)))
                (when (>= level lmax)
		  (setq ltimes (vconcat ltimes (make-vector lmax 0)) lmax (* 2 lmax)))
                (when (or (> t1 0) (> (aref ltimes level) 0))
		  (when (or headline-included headline-forced)
		    (if headline-included
                        (cl-loop for l from 0 to level do
                                 (aset ltimes l (+ (aref ltimes l) t1))))
		    (setq time (aref ltimes level))
		    (goto-char (match-beginning 0))
                    (put-text-property (point) (line-end-position)
				       (or propname :org-clock-minutes) time)
		    (when headline-filter
		      (save-excursion
                        (save-match-data
			  (while (org-up-heading-safe)
			    (put-text-property
			     (point) (line-end-position)
			     :org-clock-force-headline-inclusion t))))))
		  (setq t1 0)
		  (cl-loop for l from level to (1- lmax) do
			   (aset ltimes l 0))))))))
	(setq org-clock-file-total-minutes (aref ltimes 0))))))