Skip to content

Instantly share code, notes, and snippets.

@chrisdone
Created February 17, 2016 12:29
Show Gist options
  • Save chrisdone/cca98745c2ab5d84e35a to your computer and use it in GitHub Desktop.
Save chrisdone/cca98745c2ab5d84e35a to your computer and use it in GitHub Desktop.
org-clock-timesheet.el
(defun org-clock-timesheet ()
"Make a timesheet that can be copy/pasted into a spreadsheet of
DAY OF MONTH | CONTRACTOR NAME | DESCRIPTION OF WORK | HOURS
"
(interactive)
(let ((items (org-clock-collect-items))
(requested-month (read-from-minibuffer "Month: " (format-time-string "%Y/%m"))))
(with-output-to-temp-buffer "timesheet"
(let ((hash (make-hash-table :test 'equal)))
(mapcar
(lambda (item)
(let* ((day (plist-get item :day))
(month (plist-get item :month))
(year (plist-get item :year))
(desc (plist-get item :desc))
(hours (plist-get item :hours))
(key (cons day desc)))
(when
(string= (format "%0.2d/%0.2d" year month)
requested-month)
(puthash key
(+ (gethash key hash 0)
hours)
hash))))
items)
(mapcar
(lambda (p) (princ (cdr p)))
(sort
(let ((out nil))
(maphash
(lambda (day-desc hours)
(setq out
(cons
(cons (car day-desc)
(format "%s\tChris Done\t%s\t%.2f\n"
(car day-desc)
(cdr day-desc)
hours))
out)))
hash)
out)
(lambda (x y)
(< (car x) (car y))))))
(buffer-string))))
(defun org-clock-collect-items ()
"Collect all clocked items in a flat list."
(let ((items nil))
(save-excursion
(beginning-of-buffer)
(while
(search-forward-regexp
"^[ ]+CLOCK: \\[\\([0-9]+\\)-\\([0-9]+\\)-\\([0-9]+\\).+ => \\([0-9]+:[0-9]+\\)"
nil
t
1)
(let ((year (string-to-number (match-string 1)))
(month (string-to-number (match-string 2)))
(day (string-to-number (match-string 3)))
(hours (org-clock-parse-hours (match-string 4)))
(desc (save-excursion
(when (search-backward-regexp org-todo-line-regexp nil t 1)
(when (match-string 2)
(match-string 3))))))
(setq items
(cons (list :year year :month month :day day :hours hours :desc desc)
items)))))
items))
(defun org-clock-parse-hours (string)
"Parse STRING hh:mm into a number of hours."
(when (string-match "\\([0-9]+\\):\\([0-9]+\\)" string)
(let ((hours (match-string 1 string))
(minutes (match-string 2 string)))
(+ (string-to-number hours)
(/ (+ 0.0 (string-to-number minutes)) 60)))))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment