4

I've searched extensively online but have not found an easy solution. Maybe there is already an easy solution or some tips on doing this easily?

I am clocking in the amount of time I spend on different projects. I can summarize the clocktable using org-clock-report. However, I would like to visualize this data using either barplots for different projects (easiest), or a breakdown of how much time I spend on different projects as a function of the calendar year (most complicated).

Has anyone already tried this? Is there an easy way to parse the timestamps into a file format that makes it easy to plot in standard software such as excel or R?

Example org file:

*** Analysis
    CLOCK: [2016-06-06 Mon 21:13]--[2016-06-06 Mon 22:29] =>  1:16
    CLOCK: [2016-06-06 Mon 14:20]--[2016-06-06 Mon 17:31] =>  3:11
    CLOCK: [2016-06-06 Mon 09:50]--[2016-06-06 Mon 12:15] =>  2:25

*** Meeting
    CLOCK: [2016-06-07 Tue 09:07]--[2016-06-07 Tue 11:46] =>  2:39
    CLOCK: [2016-06-06 Mon 13:43]--[2016-06-06 Mon 14:20] =>  0:37

The idea would be to wrangle these timestamps into a file format that would be easily amenable to plotting (excel or R).

1 Answer 1

4

The Org Element API enables you to create an AST from an Org buffer. There are two options I know of to make use of it: Either create a JSON file as described in this gist and proceed in your preferred language, or filter the elements of interest in Emacs Lisp using Org-babel blocks and Org-table. Assuming I am in your example buffer:

#+begin_src elisp :results table
(nconc
 '(("month" "day" "clockin" "clockout" "duration" "status" "title"))
 '(hline)
 (let ((ast (org-element-parse-buffer 'element)))
   (org-element-map ast 'clock
     (lambda (x)
       (let ((val (org-element-property :value x)))
     `(,(calendar-month-name (org-element-property :month-start val) t)
       ,(number-to-string (org-element-property :day-start val))
       ,(concat (number-to-string (org-element-property :hour-start val))
            ":"
            (format "%02d" (org-element-property :minute-start val)))
       ,(concat (number-to-string (org-element-property :hour-end val))
            ":"
            (format "%02d" (org-element-property :minute-end val)))
       ,(org-element-property :duration x)
       ,(org-element-property :status x)
       ,@(org-element-map
         (org-element-property :parent (org-element-property :parent x))
         'headline
           (lambda (x) (org-element-property :title x)))))))))
#+end_src

#+results:
| month | day | clockin | clockout | duration | status | title    |
|-------+-----+---------+----------+----------+--------+----------|
| Jun   |   6 |   21:13 |    22:29 |     1:16 | closed | Analysis |
| Jun   |   6 |   14:20 |    17:31 |     3:11 | closed | Analysis |
| Jun   |   6 |    9:50 |    12:15 |     2:25 | closed | Analysis |
| Jun   |   7 |    9:07 |    11:46 |     2:39 | closed | Meeting  |
| Jun   |   6 |   13:43 |    14:20 |     0:37 | closed | Meeting  |

To refer to another Org buffer, wrap the code with (with-current-buffer BUFFER ...).

1
  • Great! This works. Thanks for all your help.
    – jakeyeung
    Jun 10, 2016 at 12:04

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.