9

Sometimes I want to add a clock entry for something I did after it was already done. For example I may want to add an entry CLOCK: [2017-01-28 Sa 09:35]--[2017-01-28 Sa 10:12] => 0:37 at 10:30.

There doesn't seem to be any easy way to do it. The two methods I can currently think of are:

  • Copy a previous entry and modify its time, then press C-c C-c

  • Invoke org-time-stamp-inactive twice, and then manually type in all the rest (CLOCK:, -- etc.), and then press C-c C-c.

Is there any way I can do it easier, or should I just try to define a custom function for this purpose?

1
  • Your first option is probably your best bet. I would suggest using org-clock-in or C-c C-x C-i, in combination with the C-u prefix argument SELECT , as well as the C-u C-u C-u prefix argument. Using these together and setting org-clock-continuously will allow you to "clock-in" using the last "clock-out" time as the start time - which "could" be convenient for editing the time estimates of multiple, sequential historical entries.
    – nyameko
    Jan 28, 2017 at 9:58

3 Answers 3

7

I need to do what you describe quite often. My goal is to do everything from the agenda view, i.e. having to go to the org source files as few as possible.

In order to insert a colck interval for a specific task I use helm-org-agenda-files-headings (mapped to a keyboard shortcut) which allows me to find tasks very fast. I have defined an additional helm action for this:

;; extend helm for org headings with the clock in action
    (defun dfeich/helm-org-clock-in (marker)
      "Clock into the item at MARKER"
      (with-current-buffer (marker-buffer marker)
      (goto-char (marker-position marker))
      (org-clock-in)
      (org-clock-out)))

    (eval-after-load 'helm-org
      '(nconc helm-org-headings-actions
          (list
           (cons "Clock into task" #'dfeich/helm-org-clock-in))))

This inserts a clock interval with clock-in and clock-out times set to the present time. I then use my own module org-clock-convenience (also available from MELPA) to fast adjust the times directly from the agenda view screen (need to have log lines enabled):

This involves first moving the initial time somewhere into the range between the clock out of the previous task and the next task, then hitting g (this rebuilds the screen with the task now being correctly placed in the interval). Then using org-clock-convenience-fill-gap-both to have clock-in and clock-out expand to the full iterval.

Maybe have a look at the animated gif on the org-clock-convenience module page to get an idea how the clock modification from the agenda buffer works.

3
  • Thanks. This looks like a comprehensive solution, though I normally just want to insert the clock manually on an individual file, for which I eventually decided to define a convenience function.
    – xji
    Jun 23, 2018 at 11:16
  • Why is your package marked as obsolete on MELPA? Oct 19, 2021 at 9:16
  • Hi James... I cannot see that it is labeled obsolete. It could be that in your package view you are looking at an older version of the package, and this just points out that a newer version is available. Look at this link: stackoverflow.com/questions/51932537/…
    – dfeich
    Oct 22, 2021 at 6:49
5

I wanted to do this again recently and I just hacked together a simple function which asks for the beginning and the end of the desired clock entry

(defun jx/insert-custom-clock-entry ()
  (interactive)
  (insert "CLOCK: ")
  (org-time-stamp-inactive)
  (insert "--")
  ;; Inserts the current time by default.
  (let ((current-prefix-arg '(4))) (call-interactively 'org-time-stamp-inactive))
  (org-ctrl-c-ctrl-c))

; Shortcut
(define-key evil-normal-state-map (kbd "C-'") 'jx/insert-custom-clock-entry)
(define-key evil-insert-state-map (kbd "C-'") 'jx/insert-custom-clock-entry)
2
  • There is a missing ) for (defun... which caused a parsing error for me. Please add that to the anwer. Couldn't edit since it's just one character to add. Mar 31, 2020 at 6:51
  • @scientific_explorer Thanks for pointing it out. Fixed.
    – xji
    Mar 31, 2020 at 21:47
0

Here is a solution using org-clock-in and org-clock-out to clock forgotten headers where point is at. It asks the starting time and how much time got spent on the header (duration). If there is an EFFORT-property, it will purpose the calculated remaining time as default duration.

Major issue with this approach is when there is an active clock running. It's solved here by first clocking out the active clock header, than clocking the forgotten header, and than clocking back in the active clock header. Beaware that this leads to (unnecessary) multiple clock entries in the active clock header.

Second issue is that some extra lines are needed to work directly within the org-agenda.

(defun customfunc-insert-past-clock ()
  "Insert past clock to the current header."
  (interactive)
  (let ((active-clock-marker (copy-marker org-clock-marker)))
    (unwind-protect
    (let* ((start (org-read-date t t (customfunc--org-get-timestamp-fallback)))
           (e (org-entry-get nil "EFFORT" nil nil))
           (rest-minutes (when e
                   (- (org-duration-to-minutes e)
                  (org-duration-to-minutes (or (org-clock-sum-current-item) 0.0)))))
           (duration (or (read-string "Duration: " (if (and rest-minutes (> rest-minutes 0))
                               (org-duration-from-minutes rest-minutes)
                             e))))
           (minutes (* 60 (org-duration-to-minutes duration))))
      (when (marker-buffer active-clock-marker) (org-clock-out))
      (org-clock-in nil start)
      (org-clock-out nil nil (time-add start (seconds-to-time minutes)))))
    (when (marker-buffer active-clock-marker)
      (switch-to-buffer (marker-buffer active-clock-marker)
            (goto-char active-clock-marker)
            (org-clock-in)))))

(defun customfunc--org-get-timestamp-fallback ()
  "Get timestamp with using multiple fallbacks."
  (or (org-entry-get nil "DEADLINE" nil nil)
      (org-entry-get nil "SCHEDULE" nil nil)
      (org-entry-get nil "TIMESTAMP" nil nil)))

Most of this code comes from some author on github or stack-exchange question.

Related Issue:

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.