Registro De Tiempo Con #Org-Mode | Time Clocking

Dedicado a @xaiki y Osiux

Productividad

Esta es una traducción libre de parte del maravilloso texto Organize Your Life In Plain Text! de Bernt Hansen. Gracias a él casi toda mi organización gira en torno a archivos de texto plano que los hace multiplataforma y superlivianos capaces de ser leidos desde cualquier sistema. Por lo tanto es necesario tener algún tipo de contacto con Emacs y Org-mode para que el texto les sea útil.

La traducción es parte de mi proceso de aprendizaje, es momento de que pueda registrar y cronometrar cuanto tiempo me toma una tarea a fin de poder hacer más eficiente la gestión de los proyectos. Dicho esto, los dejo con el texto.

Registrando el Tiempo

Ok, lo admito. Soy un fanático del cronometraje. Registro y cronometro todo en el trabajo. Org-mode hace de esto algo realmente sencillo y prefiero registrar muchas cosas que no las suficientes, de esa forma me es más fácil habituarme a cronometrar y registrar todo.

Esto hace posible mirar hacia atrás en el día y ver en que están gastando demasiado tiempo, o si no están dedicando el suficiente tiempo a determinados proyectos. Esto también ayuda mucho cuando necesitan estimar cuanto tiempo va a tomar hacer algo. Se pueden usar los registros de tiempo de las tareas como ayuda a la hora de preveer de forma más precisa el tiempo estimado que llevará determinada tarea

Sin estos datos que registran de tiempo, es difícil decir cuanto tomará hacer algo a posteriori.

Utilizaremos el concepto de punching in y punching out o incio de registro y salida del registro al iniciar y al finalizar la jornada laborar. Damos punch in cuando llegamos al trabajo, y damos punch out cuando almuerzamos, damos punch in al regresar y punch out al finalizar el día. De esta forma odos los minutos son registrados entre punch-in y punch-out.

Punching in registra el tiempo en todo momento en una tarea por defecto, incluso registra el tiempo en ella cuando el reloj normalmente se detendría. Con la configuración por defecto de org-mode se pierden minutos de registro durante el día, un minuto aquí, otro allá y al final todo suma. Esto es especialmente cierto cuando se escriben notas al mover una tarea al estado DONE, en estos casos el reloj de org-mode normalmente se detiene antes de que se termine de escribir la nota, y las buenas notas toman unos minutos en ser escritas.

La configuración para el registro de tiempo funciona basicamente así:

  • Punch In (inician del reloj de registro)
    • Esto registra en una tarea predefinida designada a través de org-id cuál es la tarea por defecto para el cronometrar el tiempo incluyendo el tiempo que normalmente no se registra
  • Registran el tiempo en una tarea y mueven la tarea al estado DONE cuando terminan, esto detiene el registro (clock out)
    • La detención del registro mueve el reloj a la tarea relacionada siguiente o se mueve a la tarea relacionada anterior si no hay más tareas en el proyecto.
  • Continuan registrando las tareas en las que trabajan
  • Punch Out (detiene el reloj de registro)

Pueden cambiar la tarea por defecto en la que se registra el tiempo muchas veces durante el día, pero con el movimiento automático del reloj a través del árbol de proyectos esto ya no es necesario. Sólo usen una tarea sencilla que tome el registro por defecto cuando hagan punch-in

Si hacen punch-in sobre el prefijo de una tarea del proyecto x, entonces la tarea se convierte en la tarea por defecto y todo el registro del tiempo va a ese proyecto hasta que hagan punch-out o punch-in en otra tarea.

el archivo org que contiene la tarea por defecto luce así:

todo.org:

#+FILETAGS: PERSONAL
...
* Tareas
** Organización
   :PROPERTIES:
   :CLOCK_MODELINE_TOTAL: today
   :ID:       eb155a82-92b2-4f25-a3c6-0304591af2f9
   :END:
   ...

Si estan trabajando en una tarea, entonces simplemente inicien el registro de tiempo sobre esa tarea (clock in). Al salir del registro (clocking out) de la tarea se mueve el reloj hacia una tarea relacionada con la palabra clave TODO (si es que hay alguna) y mantiene el reloj dentro del mismo árbol de tareas o proyecto. Si no hay tareas relacionadas con palabras claves TODO, entonces el reloj se mueve hacia la tarea por defecto, en este caso la tarea ** Organización, dentro del archivo org todo.org hasta que se hacen punch-out o se mueven hacia otra tarea. Cuando ocurre alguna interrupción creen una captura de tarea que mantienga el reloj en ella hasta que hagan C-c C-c.

Por ejemplo, considerando el siguiente archivo org:

* TODO Proyecto A
** NEXT Tarea 1
** TODO Tarea 2
** TODO Tarea 3
* Tareas
** TODO tareas varias

Trabajen en el archivo de la siguiente forma:

  1. Arrancan el día iniciando el reloj de registro de tiempo (punch in) con F9-I

    Esto registra el tiempo en la tarea Organización a traves de su ID en el archivo todo.org.

  2. F12-SPC para ver la agenda

    seleccionen ‘TODO tareas varias’ para trabajar en ellas y registren el tiempo presionando I ahora el reloj se mueve a ‘TODO tareas varias’

  3. Terminan la tarea y la marcan como DONE (terminada) con C-c C-t d

    Esto finaliza el registro y mueve el reloj de nuevo a la tarea Organización.

  4. Ahora quieren trabajar en el Proyecto A así que llevan el registro de timepo a la Tarea 1 haciendo I en la vista de agenda .

    Trabajan en la Tarea 1 y la marcan como DONE al terminar. Esto saca el reloj de registro de Tarea 1 y lo mueve a Proyecto A. Ahora me pongo a trabajar en la Tarea 2 y llevo el registro a ella de nuevo con I.

Durante todo el tiempo en que estan trabajando y registrando alguna subtarea del Proyecto A, todo el tiempo en ese intervalo, se aplica a algún lugar del árbol del Proyecto A. Cuando marquen el proyecto como terminado (DONE) el reloj se moverá otra vez a la tarea por defecto Organización.

Configuración del reloj

Para empezar necesitamos inicializar le reloj punch-in con lo cual se empiezan a registrar el tiempo en la tarea por defecto y mantiene el reloj corriendo. Es simplente hacer F9 I. Se puede hacer esto en cualquier lugar.

Mantener el reloj corriendo cuando mueven una tarea a estado DONE significa que se continua registrando el tiempo en las tarea del proyecto. Pueden entonces elegir la siguiente tarea del proyecto sin perder minutos mientras deciden en que van a trabajar.

Las horas del reloj, cambios de estado y otras notas se mantienen en la propiedad :LOGBOOK:

Esta es la configuración de registro de tiempo:

Configuración del relojlink
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
;;
;; Resume clocking task when emacs is restarted
(org-clock-persistence-insinuate)
;;
;; Show lot of clocking history so it's easy to pick items off the C-F11 list
(setq org-clock-history-length 23)
;; Resume clocking task on clock-in if the clock is open
(setq org-clock-in-resume t)
;; Change tasks to NEXT when clocking in
(setq org-clock-in-switch-to-state 'bh/clock-in-to-next)
;; Separate drawers for clocking and logs
(setq org-drawers (quote ("PROPERTIES" "LOGBOOK")))
;; Save clock data and state changes and notes in the LOGBOOK drawer
(setq org-clock-into-drawer t)
;; Sometimes I change tasks I'm clocking quickly - this removes clocked tasks with 0:00 duration
(setq org-clock-out-remove-zero-time-clocks t)
;; Clock out when moving task to a done state
(setq org-clock-out-when-done t)
;; Save the running clock and all clock history when exiting Emacs, load it on startup
(setq org-clock-persist t)
;; Do not prompt to resume an active clock
(setq org-clock-persist-query-resume nil)
;; Enable auto clock resolution for finding open clocks
(setq org-clock-auto-clock-resolution (quote when-no-clock-is-running))
;; Include current clocking task in clock reports
(setq org-clock-report-include-clocking-task t)

(setq bh/keep-clock-running nil)

(defun bh/clock-in-to-next (kw)
  "Switch a task from TODO to NEXT when clocking in.
Skips capture tasks, projects, and subprojects.
Switch projects and subprojects from NEXT back to TODO"
  (when (not (and (boundp 'org-capture-mode) org-capture-mode))
    (cond
     ((and (member (org-get-todo-state) (list "TODO"))
           (bh/is-task-p))
      "NEXT")
     ((and (member (org-get-todo-state) (list "NEXT"))
           (bh/is-project-p))
      "TODO"))))

(defun bh/find-project-task ()
  "Move point to the parent (project) task if any"
  (save-restriction
    (widen)
    (let ((parent-task (save-excursion (org-back-to-heading 'invisible-ok) (point))))
      (while (org-up-heading-safe)
        (when (member (nth 2 (org-heading-components)) org-todo-keywords-1)
          (setq parent-task (point))))
      (goto-char parent-task)
      parent-task)))

(defun bh/punch-in (arg)
  "Start continuous clocking and set the default task to the
selected task.  If no task is selected set the Organization task
as the default task."
  (interactive "p")
  (setq bh/keep-clock-running t)
  (if (equal major-mode 'org-agenda-mode)
      ;;
      ;; We're in the agenda
      ;;
      (let* ((marker (org-get-at-bol 'org-hd-marker))
             (tags (org-with-point-at marker (org-get-tags-at))))
        (if (and (eq arg 4) tags)
            (org-agenda-clock-in '(16))
          (bh/clock-in-organization-task-as-default)))
    ;;
    ;; We are not in the agenda
    ;;
    (save-restriction
      (widen)
      ; Find the tags on the current task
      (if (and (equal major-mode 'org-mode) (not (org-before-first-heading-p)) (eq arg 4))
          (org-clock-in '(16))
        (bh/clock-in-organization-task-as-default)))))

(defun bh/punch-out ()
  (interactive)
  (setq bh/keep-clock-running nil)
  (when (org-clock-is-active)
    (org-clock-out))
  (org-agenda-remove-restriction-lock))

(defun bh/clock-in-default-task ()
  (save-excursion
    (org-with-point-at org-clock-default-task
      (org-clock-in))))

(defun bh/clock-in-parent-task ()
  "Move point to the parent (project) task if any and clock in"
  (let ((parent-task))
    (save-excursion
      (save-restriction
        (widen)
        (while (and (not parent-task) (org-up-heading-safe))
          (when (member (nth 2 (org-heading-components)) org-todo-keywords-1)
            (setq parent-task (point))))
        (if parent-task
            (org-with-point-at parent-task
              (org-clock-in))
          (when bh/keep-clock-running
            (bh/clock-in-default-task)))))))

(defvar bh/organization-task-id "eb155a82-92b2-4f25-a3c6-0304591af2f9")

(defun bh/clock-in-organization-task-as-default ()
  (interactive)
  (org-with-point-at (org-id-find bh/organization-task-id 'marker)
    (org-clock-in '(16))))

(defun bh/clock-out-maybe ()
  (when (and bh/keep-clock-running
             (not org-clock-clocking-in)
             (marker-buffer org-clock-default-task)
             (not org-clock-resolving-clocks-due-to-idleness))
    (bh/clock-in-parent-task)))

(add-hook 'org-clock-out-hook 'bh/clock-out-maybe 'append)

Solía registrar el tiempo en las tareas por ID usando la siguiente función. Pero con el nuevo sistema de entrada y salida (punch-in y punch-out) esto ya no es necesario. F9-SPC llama a bh/clock-in-last-task que cambia el reloj a la última tarea registrada.

Configuración del reloj que ya no usolink
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
(require 'org-id)
(defun bh/clock-in-task-by-id (id)
  "Clock in a task by id"
  (org-with-point-at (org-id-find id 'marker)
    (org-clock-in nil)))

(defun bh/clock-in-last-task (arg)
  "Clock in the interrupted task if there is one
Skip the default task and get the next one.
A prefix arg forces clock in of the default task."
  (interactive "p")
  (let ((clock-in-to-task
         (cond
          ((eq arg 4) org-clock-default-task)
          ((and (org-clock-is-active)
                (equal org-clock-default-task (cadr org-clock-history)))
           (caddr org-clock-history))
          ((org-clock-is-active) (cadr org-clock-history))
          ((equal org-clock-default-task (car org-clock-history)) (cadr org-clock-history))
          (t (car org-clock-history)))))
    (widen)
    (org-with-point-at clock-in-to-task
      (org-clock-in nil))))

Iniciando el registro (Clocking In)

Cuando comienzan una tarea o continúan trabajando en una tarea se registra de cualquiera de estas formas:

  • C-c C-x C-i
  • I en la agenda
  • I tecla rápida en el primer carácter de la línea de título
  • f9 I mientras estan en la tarea dentro de la agenda
  • f9 I mientras estan en la tarea dentro de una archivo org.

Configuración de la tarea por defecto del reloj

La tarea que registra e tiempo por defecto la llamo **Organización está dentro del archivo todo.org en ella que tiendo a poner todos los registros de tiempo misceláneos. Esta es la tarea que registra el tiempo cuando se inicia el reloj (punch in) al comienzo del día laboral con F9-I. Mientras reorganizan los archivos org, leen los mails, limpian la bandeja de entrada y hacen otros trabajos planeados pero que no están en un proyecto específico se registra el tiempo en esta tarea. Haciendo punch-in en cualquier lugar dentro de emacs se inicia el reloj en esta tarea Organización.

Si quieren cambiar la tarea de registro por defecto, sólo tienen que ir a la nueva tarea en cualquier buffer y registrala con C-u C-u C-c C-x C-i-, ahora esta tarea juntará los minutos de registro misceláneos cuando el reloj normalmente se pararía.

Pueden registrar rápidamente el tiempo en la tarea por defecto con C-u C-c C-x C-i d. Otra forma es salir del registro de la tarea (clock out) repetidamente hasta que llegue a la primer tarea, cuando no hay más niveles el reloj se mueve a la tarea por default.

Usar el registro histórico del reloj para cronometrar tareas antiguas.

Pueden usar el historial del reloj para reiniciar el registro del tiempo en alguna vieja tarea que ya habían registrado o saltar directamente a una tarea que ya registrada. Suelo usar esto principalmente para iniciar el registro cuando fui interrumpido por algo.

Consideren el siguiente escenario:

  • Están trabajando y registrando en la Tarea A (Organización)
  • Son interrumpidos y cambian a la Tarea B (Documentar el uso de org-mode)
  • Completan la Tarea B (Documentar el uso de org-mode)
  • Ahora quieren continuar a la Tarea A (Organización) de nuevo para continuar.

Esto es fácil de hacer con.

  1. Iniciar el reloj en la Tarea A, trabajar en ella
  2. ir a la Tarea B (o crear una nueva tarea) y iniciar en ella el reloj
  3. Cuando terminan con la Tarea B hacer C-u C-c C-x C-i i

Esto muestra una ventana de selección del historial del reloj como la siguiente y pueden seleccionar la tarea interrumpida [i].

Buffer de selección del h1istorial del reloj C-u C-c C-x C-i

1
2
3
4
5
6
7
8
9
10
11
Default Task
    [d] norang          Organization                          <-- Task B
    The task interrupted by starting the last one
    [i] norang          Organization                          <-- Task B
    Current Clocking Task
    [c] org             NEXT Document my use of org-mode      <-- Task A
    Recent Tasks
    [1] org             NEXT Document my use of org-mode      <-- Task A
    [2] norang          Organization                          <-- Task B
    ...
    [Z] org             DONE Fix default section links        <-- 35 clock task entries ago

Registrandolo todo - Crear nuevas tareas

En orden de registrar todo, necesitan una tarea para todo. Y eso está bien para proyectos y planes, pero las interrupciones ocurren de manera inevitable y necesitan algún lugar para registrar el tiempo que dedican a esas interrupciones.

Para lidiar con esto crearemos una nueva captura de tarea que registre lo que vamos a hacer. El flujo de trabajo sería algo así:

  • Están trabajando y registrando alguna tarea y ocurre una interrupción.
  • Creen una tarea rápida de tipo diario C-c c j.
  • Tipeen el encabezado.
  • Hagan lo esa cosa (comer, hacer el mate, lo que sea).
  • Guardenla C-c C-c, esto restaura el reloj en la tarea en la que estaban trabajando.
  • Inicien otra tarea o continúen con lo que estaban haciendo.

Esto significa que pueden ignorar el detalle como a dónde pertenece realmente la tarea en el esquema de sus archivos org y continuar con lo que estaban haciendo. Reorganizar (refilling) muchas tareas más adelante en grupo cuando sea conveniente hacer el refill ahorra tiempo a largo plazo.

Si se trata de una tarea solitaria y poco interesante (un café o hacer el mate). Creen una captura de diario que irá directo al árbol del archivo diary.org. Si es una tarea que necesita ser trackeada y marcada como hecha (DONE), y se aplica a algún proyecto. Entonces creen una captura de tarea y luego la reorganizan.

Encontrando tareas para cronometrar

Para encontrar una tarea en la que trabajar uso uno de las siguientes opciones (Listadas en orden de uso frecuente)

  • Usen del historial del reloj C-u C-c C-x C-i para volver a algo que estaban registrando y que no hayan finalizado.
  • Elijan algo de bloque “today” de la agenda, algún ítem en estado SCHEDULED o DEADLINE que sea necesario realizar.
  • Elijan algo de la vista NEXT de la agenda, trabajen el alguna tarea incompleta.
  • Elijan algo de otra lista de tareas
  • Usen una vista de agenda con algún filtro para elegir algo en lo que trabajar.

Al iniciar el reloj en la tarea que eligieron restringirá la vista de la agenda a ese proyecto, de manera que se puedan enfocar sólo en esa cosa durante un período de tiempo.

Editando entradas del reloj

Algunas veces es necesario editar alguna entrada del reloj para que refleje correctamente la realidad. Hago esto en tal vez 2 o 3 entradas en una semana.

Otras veces no puedo cronometrar una tarea porque estoy lejos de la computadora. En estos casos la tarea previa en la que estaba continua registrándose y registra el tiempo de ambas tareas creando un registro incorrecto.

Para estos casos, creo una nota del tiempo que me toma la tarea y cuando vuelvo a mi computadora inicio el reloj en la tarea correcta y edito el inicio y el final del historial del registro de tiempo.

Para ver rápidamente la línea del reloj de una entrada usen el modo log de la agenda F12 a l muestra todas las líneas de registro del día. Usen esto para navegar rapidamente a la línea que tengan que editar. F11 nos lleva a la tarea que actualmente está siendo registrada, pero el modo log de la agenda es mejor para encontrar y visitar registros de reloj vejos.

Usen F12 a l para abrir la agenda en modo log y mostrar sólo las entradas con registro de tiempo. Muevan el cursor hacia la línea que necesitan editar, aprieten TAB y ya estarán ahí.

Para editar una entrada de reloj sólo pongan el cursor en la parte del dato que quieren editar (usen el teclado, no el mouse, ya que el click en la marca de tiempo con el mouse los llevará de nuevo a la agenda de ese día, y presionen S-<up arrow> o S-<down arrow> para cambiar los registros de tiempo.

La siguiente configuración hace que la edición del tiempo use incrementos discretos en los intervalos de los minutos (sin redondeo):

incrementos discretoslink
1
(setq org-time-stamp-rounding-minutes (quote (1 1)))

Editar el tiempo con la combinación de teclas shift y flecha arriba también actualiza la sumatoria de la cuenta del reloj, lo cual es muy conveniente.

Siempre comprueben, viéndo en el modo log de la agenda, no haber creado superposiciones de tareas. Hay una nueva vista en la agenda para esto - sólo tecleen v c en la vista diaria de la agenda y se muestran gaps y superposiciones del reloj.

Busco que mis registros de tiempo sean lo más acertados posibles.

La siguiente configuración muestra los gaps de registro de hasta 1 minuto.

verificación de gapslink
1
2
3
4
5
    (setq org-agenda-clock-consistency-checks
          (quote (:max-duration "4:00"
                  :min-duration 0
                  :max-gap 0
                  :gap-ok-around ("4:00"))))

Imagen: productividad

Alvar

Alvar Maciel

Docente, busco entender el engranaje tecnológico en el que estamos metides. Trabajo y escribo acerca de la educación.

Read More