I use org-mode clocks extensively for task tracking, with one exception. End of day. Depending on my location, amount of haste (trains or battery power) etc. I sometimes neglect clocking out at day end.

Is there a setting to set the maximum allowed day-time (same day) end?

Example: I start an action at 16:35, I run for a train at 17:45. I forgot to log out. On clocking in the next morning - I don't want the keep value of working on the last action overnight, but to a maximum time of say 17:30.

  • 1
    I deleted my answer with kill-emacs-hook. At first sight I overlooked your statement that you forgot to log out. In that case kill-emacs-hook does not help. Sorry. – Tobias Jan 13 '16 at 8:21
  • 1
    I have replaced my wrong answer (kill-emacs-hook) with an answer that meets your specification quite well. – Tobias Jan 13 '16 at 16:38

The following advice of org-clock-in does quite exactly what you want. If the clock from yesterday or before is still running you are clocked-out at the time org-clock-out-latest-back-dated on the day the clock started.

;; Just for customization of `org-clock-out-latest-back-dated':
(defun time-string-hh:mm-validate (time)
  "Returns nil if TIME has the correct format hh:mm.
Where hh are the digits of the number of hours and mm are the digits of the number of minutes.
TIME can be a string or a widget."
  (let ((val (if (stringp time) time (widget-value time))))
    (if (and (stringp val)
         (string-match "^\\([0-9]\\{1,2\\}\\):\\([0-9]\\{1,2\\}\\)$" val)
         (< (string-to-number (match-string 1)) 24)
         (< (string-to-number (match-string 2)) 60))
      (if (stringp time)
    (widget-put time :error "String does not match format hh:mm.")

(define-widget 'time-string-hh:mm 'editable-field
  "Time string with format hh:mm."
  :size 5
  :format "Time (hh:mm): %v "
  :validate 'time-string-hh:mm-validate)

(defcustom org-clock-out-latest-back-dated "17:30"
  "Time as string with format hh:mm to check out on back-dated days."
  :group 'org-clock
  :type 'time-string-hh:mm)

;; The actual advice:
(defadvice org-clock-in (before clock-out-back-dated activate)
  "If there is a running clock from a back-dated day
clock it out at `org-clock-out-latest-back-dated' on that day."
  (when (and (org-clocking-p)
         (> (time-to-days (current-time)) (time-to-days org-clock-start-time)))
    (let ((time (decode-time org-clock-start-time))
      (hhmm (mapcar 'string-to-number (progn
                        (when (time-string-hh:mm-validate org-clock-out-latest-back-dated)
                          (error "Wrong time format in `org-clock-out-latest-back-dated'"))
                        (split-string org-clock-out-latest-back-dated ":")))))
      (setf (nth 1 time) (cadr hhmm))
      (setf (nth 2 time) (car hhmm))
      (org-clock-out nil nil (apply 'encode-time time)))))
  • 1
    Thanks Tobias, this is the missing param I was hoping I overlooked. I kept searching for "day end" type keywords. – OrgAddict Jan 14 '16 at 8:50

You could schedule a command to clock out at 17:30. Midnight Mode lets you schedule commands to run at a specified time.

  • Midnight mode looks helpful, thanks. Will use that to run my weekly cleanup scripts. – OrgAddict Jan 14 '16 at 8:51

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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