Created
February 17, 2016 12:29
-
-
Save chrisdone/cca98745c2ab5d84e35a to your computer and use it in GitHub Desktop.
org-clock-timesheet.el
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(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