Build a chart from Org-mode clocks
Org-mode is a great todo and agenda application. It's possible to use it to clock how much time you spend on a task. I've been clocking my work for a few months using org-mode. I love that I can get a summary of how much time I have spent on each stuff I do. However, it's difficult to see how much time you spend daily. You have to look at each clock entry and sum the durations. Not very friendly. My idea was to chart the hours spent per day. You put the cursor on any task and you get a bar chart showing you how much time was spent per day.
It's turning this:
*** project1
**** task1
CLOCK: [2010-11-20 Sun 19:42]--[2010-11-20 Sun 20:14] => 0:32
CLOCK: [2010-11-20 Sun 18:54]--[2010-11-20 Sun 19:24] => 0:30
CLOCK: [2010-11-20 Sun 17:25]--[2010-11-20 Sun 17:40] => 0:15
CLOCK: [2010-11-20 Sun 15:07]--[2010-11-20 Sun 15:45] => 0:38
CLOCK: [2010-11-20 Sun 10:06]--[2010-11-20 Sun 12:37] => 2:31
CLOCK: [2010-11-19 Sat 17:21]--[2010-11-19 Sat 19:33] => 2:12
CLOCK: [2010-11-19 Sat 14:52]--[2010-11-19 Sat 16:53] => 2:01
CLOCK: [2010-11-18 Fri 17:45]--[2010-11-18 Fri 18:27] => 0:42
CLOCK: [2010-11-18 Fri 11:17]--[2010-11-18 Fri 15:20] => 4:03
**** task2
:LOGBOOK:
CLOCK: [2010-11-19 Sat 12:51]--[2010-11-19 Sat 14:52] => 2:01
CLOCK: [2010-11-18 Fri 17:08]--[2010-11-18 Fri 17:45] => 0:37
CLOCK: [2010-11-18 Fri 11:17]--[2010-11-18 Fri 11:17] => 0:00
CLOCK: [2010-11-17 Thu 12:40]--[2010-11-17 Thu 13:05] => 0:25
CLOCK: [2010-11-17 Thu 10:16]--[2010-11-17 Thu 11:58] => 1:42
CLOCK: [2010-11-16 Wed 19:32]--[2010-11-16 Wed 20:29] => 0:57
CLOCK: [2010-11-16 Wed 14:06]--[2010-11-16 Wed 16:04] => 1:58
CLOCK: [2010-11-16 Wed 11:55]--[2010-11-16 Wed 13:00] => 1:05
CLOCK: [2010-11-15 Tue 16:32]--[2010-11-15 Tue 17:59] => 1:27
CLOCK: [2010-11-15 Tue 10:55]--[2010-11-15 Tue 12:27] => 1:32
CLOCK: [2010-11-14 Mon 18:05]--[2010-11-14 Mon 19:52] => 1:47
CLOCK: [2010-11-14 Mon 16:10]--[2010-11-14 Mon 17:46] => 1:36
CLOCK: [2010-11-14 Mon 14:40]--[2010-11-14 Mon 15:24] => 0:44
CLOCK: [2010-11-14 Mon 09:50]--[2010-11-14 Mon 11:34] => 1:44
CLOCK: [2010-11-13 Sun 22:22]--[2010-11-13 Sun 23:17] => 0:55
CLOCK: [2010-11-13 Sun 15:23]--[2010-11-13 Sun 18:56] => 3:33
CLOCK: [2010-11-12 Sat 14:25]--[2010-11-12 Sat 17:08] => 2:43
CLOCK: [2010-11-11 Fri 19:25]--[2010-11-11 Fri 19:52] => 0:27
CLOCK: [2010-11-11 Fri 15:30]--[2010-11-11 Fri 18:15] => 2:45
CLOCK: [2010-11-11 Fri 10:26]--[2010-11-11 Fri 12:26] => 2:00
CLOCK: [2010-11-10 Thu 15:12]--[2010-11-10 Thu 18:49] => 3:37
CLOCK: [2010-11-10 Thu 10:08]--[2010-11-10 Thu 12:42] => 2:34
CLOCK: [2010-11-09 Wed 22:18]--[2010-11-10 Thu 00:13] => 1:55
CLOCK: [2010-11-09 Wed 15:09]--[2010-11-09 Wed 15:59] => 0:50
CLOCK: [2010-11-09 Wed 14:05]--[2010-11-09 Wed 14:50] => 0:45
:END:
Into this:
Behind the scene, I've used Google chart api, and a few lines of emacs lisp. If you like that, copy the code below in your .emacs and bind a key to org-chart-clocks-current-item (define-key org-mode-map [f4] 'org-chart-clocks-current-item).
(defun org-time-delta-seconds (time-string seconds)(format-time-string"%Y-%m-%d"(seconds-to-time(+ (org-float-time (apply 'encode-time(org-parse-time-string time-string)))seconds))))(defun org-list-clocks-current-item ()"Extract clocked hours per day of current item"(save-excursion(save-restriction(org-narrow-to-subtree)(goto-char (point-max))(let ((re (concat "^[ \t]*" org-clock-string"[ \t]*\\(?:\\[\\([0-9-]+\\).*?\\]-+\\(\\[.*?\\]\\)\\|=>[ \t]+\\([0-9]+\\):\\([0-9]+\\)\\)"))(one-day (* 3600 24)))(re-search-backward re nil t)(setq match (match-string 2)ts (substring match 1 11)te (org-time-delta-seconds match one-day)res '()dates '())(while (< (org-float-time(apply 'encode-time(org-parse-time-string ts)))(org-float-time (current-time)))(org-clock-sum ts te)(setq res (cons (/ org-clock-file-total-minutes 60.0) res)dates (cons (substring ts 8 10) dates))(setq ts tete (org-time-delta-seconds ts one-day)))(list dates res)))))(defun org-chart-clocks-current-item ()"Request a Google Chart with the clocked time of the current item."(interactive)(let* ((x (org-list-clocks-current-item))(dates (reverse (car x)))(res (reverse (cadr x)))(active-days (length (remove-if (lambda (x) (= x 0)) res)))(sum-hours (reduce (lambda (a b) (+ a b)) res)))(browse-url (format "http://chart.apis.google.com/chart?chxl=1:|%s&chxr=0,0,8|1,0,105&chxt=y,x&chbh=15&chs=600x400&cht=bvg&chco=80C65A&chds=0,8&chd=t:%s&chg=0,25,0,0&chma=|5,10&chtt=Clocked+Activity+(%d+days,+%d+hours)&chm=h,FF0000,0,%f,1"(mapconcat (lambda (x) x) dates "|")(mapconcat (lambda (x) (format "%s" x)) res ",")active-dayssum-hours(/ sum-hours active-days 8)))))