emacs-orgmode
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Orgmode] Visual representation of clocked time


From: Carsten Dominik
Subject: Re: [Orgmode] Visual representation of clocked time
Date: Tue, 3 Nov 2009 18:03:43 +0100

Hi Gennady,

thanks for sharing!

- Carsten

On Nov 2, 2009, at 10:16 PM, Gennady Trafimenkov wrote:

Hello everyone,

I was thinking that it would be nice to have a visual representation
of clocked time. It could give you a quick overview of when and how
long you had been working on a particular task.

For example, you have a subtree like this:

** very important task
  CLOCK: [2009-10-03 Sat 22:02]--[2009-10-03 Sat 23:21] =>  1:19
  CLOCK: [2009-10-04 Sun 23:53]--[2009-10-05 Mon 02:10] =>  2:17
  CLOCK: [2009-10-06 Tue 14:10]--[2009-10-06 Tue 14:50] =>  0:40
  CLOCK: [2009-10-07 Wed 21:25]--[2009-10-08 Thu 00:21] =>  2:56
  CLOCK: [2009-10-13 Tue 01:52]--[2009-10-13 Tue 02:52] =>  1:00
  CLOCK: [2009-10-13 Tue 20:58]--[2009-10-13 Tue 23:32] =>  2:34
  CLOCK: [2009-10-14 Wed 23:20]--[2009-10-15 Thu 00:55] =>  1:35
  CLOCK: [2009-10-16 Fri 14:14]--[2009-10-16 Fri 14:53] =>  0:39
  some text here

You press a combination of keys and get a table like this:

|---------------+-----+-----+-----+-----+-----+-----+-----+------|
| Week Starting | Mon | Tue | Wed | Thu | Fri | Sat | Sun | tt,h |
|---------------+-----+-----+-----+-----+-----+-----+-----+------|
|    2009-09-28 |     |     |     |     |     |  79 | 137 |  3.6 |
|    2009-10-05 |     |  40 | 176 |     |     |     |     |  3.6 |
|    2009-10-12 |     | 214 |  95 |     |  39 |     |     |  5.8 |
|---------------+-----+-----+-----+-----+-----+-----+-----+------|

The table contains total number of clocked minutes for every day and
total number of hours for every week.

If I could write such a thing in Emacs lisp, I would do that.  But
unfortunately I can't.  So, I wrote a python script and small function
in lisp to call it.  I am posting them here in hope that it might be
useful for someone.

Org-mode is an excellent thing. Thank you!

Best regards,
Gennady Trafimenkov

============================================================
===                                                      ===
============================================================

(defun gt/org-get-clocked-time-stat-on-subtree ()
 "Calculate nice table with statistics of clocked time.
  It puts results into buffer '*clocked-time-stat*'.
  When called with C-u, it copies results into the kill ring.
  GNU General Public License version 3 or later."
 (interactive)
 (let ((outputbuffer "*clocked-time-stat*"))
   (save-excursion
     (outline-mark-subtree)
     (shell-command-on-region (region-beginning) (region-end)
                              "python ~/bin/create-clock-table.py"
outputbuffer)
     (if (equal current-prefix-arg '(4))
         (if (get-buffer outputbuffer)
             (progn
               (with-current-buffer outputbuffer
                 (mark-whole-buffer)
                 (kill-new (filter-buffer-substring
(region-beginning) (region-end))))))))))

============================================================
=== create-clock-table.py ==================================
============================================================

#/usr/bin/env python
#
# GNU General Public License version 3 or later
#
# This script extracts all record of this kind from the standart input:
#
#    CLOCK: [2009-10-17 Sat 21:47]--[2009-10-17 Sat 23:10] =>  1:23
#
# then aggregates data and build table with statistics like this:
#   |---------------+-----+-----+-----+-----+-----+-----+-----+------|
#   | Week Starting | Mon | Tue | Wed | Thu | Fri | Sat | Sun | Tot. |
#   |---------------+-----+-----+-----+-----+-----+-----+-----+------|
#   |    2009-08-03 |     |     |     |     |     |     |     |    0 |
#   |    2009-08-10 |     |     |     |     |     |     |     |    0 |
#   |    2009-08-17 |     |     |     |  75 |  60 |  60 |  15 |  210 |
#   |    2009-08-24 |  75 |  60 |  60 |  70 |     |     |     |  265 |
#   |    2009-08-31 |     |  10 |     |     |     |     |     |   10 |
#   |---------------+-----+-----+-----+-----+-----+-----+-----+------|
import sys
import re
import datetime

if __name__ == '__main__':

   dailyStat = {}
   # we are going to extract records like:
   #   CLOCK: [2009-10-17 Sat 21:47]--[2009-10-17 Sat 23:10] =>  1:23
   timeExtractor = re.compile('^\s*CLOCK:
\[(\d{4})-(\d\d)-(\d\d).*\]--\[.*\] =>\s+(\d+):(\d\d)')
   for line in sys.stdin.readlines():
       match = timeExtractor.match(line)
       if match:
           year, month, day = int(match.group(1)),
int(match.group(2)), int(match.group(3))
           hours, minutes = int(match.group(4)), int(match.group(5))
           date = datetime.date(year, month, day)
           minutes += hours * 60
           # print date, minutes

           dailyStat.setdefault(date, 0)
           dailyStat[date] += minutes

   if len(dailyStat) == 0:
       sys.exit(0)

   minDate = min(dailyStat.keys())
   maxDate = max(dailyStat.keys())
   firstWeek = minDate - datetime.timedelta(minDate.weekday())
   lastWeek = maxDate - datetime.timedelta(maxDate.weekday())

   # calculate weekly stat
   ############################################################

   weeklyStat = {}
   week = firstWeek
   while week <= lastWeek:
       weeklyStat[week] = [0, 0, 0, 0, 0, 0, 0, 0]
       week += datetime.timedelta(7)

   biggestNumber = 0
   for day in dailyStat.keys():
       weekday = day.weekday()
       week = day - datetime.timedelta(weekday)
       weeklyStat[week][weekday] = dailyStat[day]
       weeklyStat[week][7] += dailyStat[day]
       biggestNumber = max(biggestNumber, dailyStat[day])

   def PrintTableLine(firstColumn, otherColumns, otherColumnsWidth):
       cellTemplate = " %%%ds |" % otherColumnsWidth
       line = "| %13s |" % firstColumn
       for i in otherColumns:
           if i == 0:
               line += cellTemplate % ""
           else:
               line += cellTemplate % i
       print line

   def PrintTableDelimiter(numOfColumns, otherColumnsWidth):
       column = "-" * (otherColumnsWidth + 2)
       line = "|" + "-" * (13 + 2)
       for i in xrange(1, numOfColumns+1):
           line += "+"
           line += column
       line += "|"
       print line

   # printing the weekly stat table
   ############################################################

   columnWidth = max(4, len("%d" % biggestNumber) + 1)
   PrintTableDelimiter(8, columnWidth)
PrintTableLine("Week Starting", ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat",
                                    "Sun", "tt,h"], columnWidth)
   PrintTableDelimiter(8, columnWidth)
   cellTemplate = " %%%ds |" % columnWidth
   week = firstWeek
   while week <= lastWeek:
       # convert total number of minutes in number of hours
weeklyStat[week][7] = "%0.1f" % (float(weeklyStat[week][7]) / 60)
       PrintTableLine(week.isoformat(), weeklyStat[week], columnWidth)
       week += datetime.timedelta(7)
   PrintTableDelimiter(8, columnWidth)

============================================================


_______________________________________________
Emacs-orgmode mailing list
Remember: use `Reply All' to send replies to the list.
address@hidden
http://lists.gnu.org/mailman/listinfo/emacs-orgmode

- Carsten







reply via email to

[Prev in Thread] Current Thread [Next in Thread]