組織:時計を合わせた時間を時間単位で表示する

私たちには新しい職場のマネージャーがいて、彼はタイムシートを出したいと思っています。問題はない、私はorg-modeを持っている。を除いて、彼はこのように報告された時間が欲しい:

0900-1000 Customer  Project  xMinutes
0900-1000 Customer2 Project2 yMinutes
1000-1100 Customer  Project3 zMinutes

言い換えれば、1時間に3つの時間に時間を合わせると、その時間に対して3つのラインが必要になります。これは、タスクに対して、私が費やした3分分を示しています。当然のことながら、私の組織ファイルは、それらの顧客の下で見出しとして異なる顧客のためのタスクを持っているので、理論的には、これらの2つの列は簡単でなければなりません。

私は組織のハッキングにあまり経験がありません。私はこのように時間をどのように崩壊させるのかを考え出すことはできません。だから私は誰かに私のためにそれをするように頼むと思った:)

うまくいけば、答えは、Orgのマニュアルの中で私を見つめていません。

** Greenwich Consultancy
   :LOGBOOK:
   CLOCK: [2016-02-18 Thu 10:40]--[2016-02-18 Thu 11:10] =>  0:30
   CLOCK: [2016-01-13 Wed 14:48]--[2016-01-13 Wed 15:29] =>  0:41
   CLOCK: [2016-01-12 Tue 11:00]--[2016-01-12 Tue 16:53] =>  5:53
   :END:
** PU [2/2]
*** DONE Identify PU Open equella block
    CLOSED: [2015-10-26 Mon 09:09]
    :LOGBOOK:
    CLOCK: [2015-10-09 Fri 14:10]--[2015-10-09 Fri 16:06] =>  1:56
    :END:
*** Update UAT 
    :LOGBOOK:
    CLOCK: [2016-02-17 Wed 10:03]--[2016-02-17 Wed 10:16] =>  0:13
    CLOCK: [2015-11-17 Tue 09:12]--[2015-11-17 Tue 09:18] =>  0:06
    CLOCK: [2015-11-16 Mon 14:49]--[2015-11-16 Mon 15:00] =>  0:11
    :END:
*** PSMD Block
    :LOGBOOK:
    CLOCK: [2016-02-26 Fri 16:26]--[2016-02-26 Fri 16:53] =>  0:27
    CLOCK: [2016-02-11 Thu 14:27]--[2016-02-11 Thu 14:47] =>  0:20
    CLOCK: [2016-02-09 Tue 16:17]--[2016-02-09 Tue 16:31] =>  0:14
    CLOCK: [2016-02-09 Tue 14:24]--[2016-02-09 Tue 15:02] =>  0:38
    CLOCK: [2016-02-09 Tue 12:13]--[2016-02-09 Tue 13:01] =>  0:48
    CLOCK: [2016-02-09 Tue 10:15]--[2016-02-09 Tue 10:58] =>  0:43
    CLOCK: [2016-02-05 Fri 14:27]--[2016-02-05 Fri 16:36] =>  2:09
    CLOCK: [2016-02-05 Fri 11:11]--[2016-02-05 Fri 12:02] =>  0:51
    CLOCK: [2016-02-05 Fri 10:36]--[2016-02-05 Fri 10:53] =>  0:17
    CLOCK: [2016-02-03 Wed 09:39]--[2016-02-03 Wed 10:24] =>  0:45
    CLOCK: [2016-02-02 Tue 16:39]--[2016-02-02 Tue 17:00] =>  0:21
    CLOCK: [2016-01-29 Fri 12:27]--[2016-01-29 Fri 12:33] =>  0:06
    :END:       
*** Server tidy
**** STARTED Check TII code on UAT
     :LOGBOOK:
     CLOCK: [2016-02-25 Thu 16:59]--[2016-02-26 Fri 09:22] => 16:23
     :END:
**** DONE Update Coursework M26 branch
     CLOSED: [2016-02-25 Thu 16:59]
     - State "DONE"       from "STARTED"    [2016-02-25 Thu 16:59]
     :LOGBOOK:
     CLOCK: [2016-02-25 Thu 16:56]--[2016-02-25 Thu 16:59] =>  0:03
     :END:   
*** UAT PSMD Roamers problem
    :LOGBOOK:
    CLOCK: [2016-02-25 Thu 11:19]--[2016-02-25 Thu 11:33] =>  0:14
    :END:
*** Gradebook problem
    :LOGBOOK:
    CLOCK: [2016-02-26 Fri 15:35]--[2016-02-26 Fri 16:26] =>  0:51
    :END:

例えば、

CLOCK: [2016-02-05 Fri 11:11]--[2016-02-05 Fri 12:02] =>  0:51

2つの出力行を生成する必要があります(タブまたはコンマ区切り付き)。

1000-1100 PU PSMD Block 49
1100-1200 PU PSMD Block  2
7
これは、正常な時計テーブルを生成するものと同様に、Org 動的ブロックを使用して実装するのが最適です。 マニュアルには、その作成方法が記載されています。私は毎月の作業パッケージ時間を報告するための互換CSVに匹敵する機能を持っています。あなたのケースでは、これらの日常的なレポートが必要ですか?形式はちょっと変わっているかもしれませんが、できます...あなたの組織ファイルが顧客、プロジェクト、タスク、サブタスクに関してどのように構造化されているかの小さな例を教えてください。
追加された 著者 Ross,
分を org-clock-sum で抽出することは可能です。オプションの引数として、見出しのフィルタ、開始時刻、終了時刻を与えることができます。私が正しく覚えていれば、org 8.2ではこの機能に問題がありますが、org 8.3.3で機能します。私はそれについては分かりません。結果として、 emacs-versionorg-version も報告する必要があります。
追加された 著者 Mike Spivey,
@Tobias Org 8.3.3、およびEmacs 24.5.1。
追加された 著者 Shreemay Panhalkar,
@dfeich私は自分のデータの小さなセクションを追加しました。トップレベルの見出し(つまり、単一の*レベル)は、「スプリント#13」や「サポートワーク」などのようなものです。第2レベルは、クライアントと第3レベルの特定のタスクです。
追加された 著者 Shreemay Panhalkar,

2 答え

私の解決策は、トビアスのものより短くは決してありません。それは私が副産物の1つに関心を持っていなかったなら、私はおそらくそれを書いていないでしょう:特定の時間内に完全な見出し情報インターバルは、さらなる処理のための基礎である。この関数と他のヘルパーに基づいて、私はあなたが通常のorgのクロックテーブルブロックのように使うことができる動的ブロックを実装します。 BEGIN行の C-c C-c を押すと、次のように展開されます。

  #+BEGIN: nagora-report :buffer "nagora-example.org" :day 2016-02-05
  #+END:

  #+BEGIN: nagora-report :buffer "nagora-example.org" :day 2016-02-25
  #+END:

これらの2つのブロックは次のように拡張されます:

  #+BEGIN: nagora-report :buffer "nagora-example.org" :day 2016-02-05
  #+CAPTION: timesheet for day 2016-02-05
  |        Time | Customer | Task       | Minutes |
  |-------------+----------+------------+---------|
  | 10:00-11:00 | PU [2/2] | PSMD Block |      17 |
  | 11:00-12:00 | PU [2/2] | PSMD Block |      49 |
  | 12:00-13:00 | PU [2/2] | PSMD Block |       2 |
  | 14:00-15:00 | PU [2/2] | PSMD Block |      33 |
  | 15:00-16:00 | PU [2/2] | PSMD Block |      60 |
  | 16:00-17:00 | PU [2/2] | PSMD Block |      36 |
  |-------------+----------+------------+---------|
  |       TOTAL |          |            |     197 |
  #+TBLFM: @>$>=vsum(@[email protected])
  #+END:

  #+BEGIN: nagora-report :buffer "nagora-example.org" :day 2016-02-25
  #+CAPTION: timesheet for day 2016-02-25
  |        Time | Customer | Task                          | Minutes |
  |-------------+----------+-------------------------------+---------|
  | 11:00-12:00 | PU [2/2] | UAT PSMD Roamers problem      |      14 |
  | 16:00-17:00 | PU [2/2] | STARTED Check TII code on UAT |       1 |
  | 16:00-17:00 | PU [2/2] | Update Coursework M26 branch  |       3 |
  | 17:00-18:00 | PU [2/2] | STARTED Check TII code on UAT |      60 |
  | 18:00-19:00 | PU [2/2] | STARTED Check TII code on UAT |      60 |
  | 19:00-20:00 | PU [2/2] | STARTED Check TII code on UAT |      60 |
  | 20:00-21:00 | PU [2/2] | STARTED Check TII code on UAT |      60 |
  | 21:00-22:00 | PU [2/2] | STARTED Check TII code on UAT |      60 |
  | 22:00-23:00 | PU [2/2] | STARTED Check TII code on UAT |      60 |
  |-------------+----------+-------------------------------+---------|
  |       TOTAL |          |                               |     378 |
  #+TBLFM: @>$>=vsum(@[email protected])
  #+END:

括弧内のカウンターは、必要に応じて簡単にクリーンアップできます。現在のところ、動的ブロックはオープンバッファ(:buffer 引数)を必要としますが、それをファイルパスに変更するのは簡単です。

私はまだこの特別なタイムシートレポーティングフォーマットには不思議ではありません。なぜなら、それは翻訳不変ではないからです.1時間後またはある時間後に始めると、同じ量の作業が異なるように見えます。しかし、時には管理と議論するよりも、そのような機能を実装する方が短い場合もあります;-)

私はこれが役に立つと思います。それは確かに少しきれいにすることができ、より一貫しています。

(defun dfeich/org-clock-get-tr-for-ivl (buffer tstart-str tend-str &optional limit)
  "Return clocking information touching a given time interval."
  (cl-assert (and buffer (get-buffer buffer)) nil "Error: :buffer must be defined")
  (with-current-buffer buffer
    (save-excursion
      (let ((re (concat "^\\(\\*+[ \t]*.*\\)\\|^[ \t]*"
            org-clock-string
            "[ \t]*\\(?:\\(\\[.*?\\]\\)-+\\(\\[.*?\\]\\)\\|=>[ \t]+\\([0-9]+\\):\\([0-9]+\\)\\)"))
        (counter 0)
        (tmphd "BEFORE FIRST HEADING")
        (tstart (org-time-string-to-seconds tstart-str))
        (tend (org-time-string-to-seconds tend-str))
        (limit (or limit (point-max)))
        headings timelst
        lvl title result ts te)
    (goto-char (point-min))
    (cl-block myblock
      (while (re-search-forward re nil t)
        (cond
         ;; found a org heading
         ((match-end 1)
          (if (> (length timelst) 0)
          (setq result (nconc result (list (list
                            (copy-sequence headings)
                            timelst)))))
          (setq tmphd (org-heading-components)
            lvl (car tmphd)
            title (nth 4 tmphd)
            timelst nil)
          ;; maintain a list of the current heading hierarchy
          (cond
           ((> lvl (length headings))
        (setq headings  (nconc headings `(,title))))
           ((= lvl (length headings))
        (setf (nth (1- lvl) headings) title))
           ((< lvl (length headings))
        (setq headings (cl-subseq headings 0 lvl))
        (setf (nth (1- lvl) headings) title))))
         ;; found a clock line with 2 timestamps
         ((match-end 3)
          (setq ts (save-match-data (org-time-string-to-seconds
                     (match-string-no-properties 2)))
            te (save-match-data (org-time-string-to-seconds
                     (match-string-no-properties 3))))
          ;; the clock lines progress from newest to oldest. This
          ;; enables skipping the rest if this condition is true
          (if (> tstart te)
          (if (re-search-forward "^\\(\\*+[ \t]*.*\\)" nil t)
              (beginning-of-line)
            (goto-char (point-max)))
        (when (> tend ts)
          (setq timelst (nconc timelst (list
                        (list (match-string-no-properties 2)
                              (match-string-no-properties 3)))))))))
        (when (>= (point) limit)
          (cl-return-from myblock))))
    (if (> (length timelst) 0)
        (setq result (nconc result (list (list (copy-sequence headings)
                           timelst)))))
    result))))

(defun dfeich/org-slice-tr (tstart-str tend-str cutstart-str cutend-str)
  "Return time slice of a time range in minutes."
  (let ((tstart (org-time-string-to-seconds tstart-str))
    (tend (org-time-string-to-seconds tend-str))
    (cutstart (if (stringp cutstart-str)
              (org-time-string-to-seconds cutstart-str)
            cutstart-str))
    (cutend (if (stringp cutend-str)
            (org-time-string-to-seconds cutend-str)
          cutend-str))
    result)
    (setq result (max 0
              (/  (- (min tend cutend) (max tstart cutstart))
              60)))))

(defun dfeich/org-clock-hourly-report (struct tstart-str tend-str)
  "Return a structure containing a per hour report within an interval."
  (let* ((tstart (org-time-string-to-seconds tstart-str))
     (tend (org-time-string-to-seconds tend-str))
     (delta 3600)
     (intvls (cl-loop for tm from tstart to (- tend delta) by delta
              collect `(,tm ,(+ tm delta))))
     result)
    ;; iterate over the intervals for the final table
    (cl-loop for iv in intvls
         collect (list
              iv
              (let* ((cutstart (car iv))
                 (cutend (cadr iv))
                 (tmsum 0.0)
                 headings trlst)
            ;; iterate over the task structure
            (cl-loop
             for item in struct
             do (progn
                  (setq headings (car item)
                    trlst (cadr item)
                    ;; sum up the parts of the time
                    ;; ranges falling into this
                    ;; interval
                    tmsum (apply
                       #'+
                       (mapcar
                        (lambda (tr)
                          (dfeich/org-slice-tr (car tr)
                                   (cadr tr)
                                   cutstart
                                   cutend))
                        trlst))))
             if (> tmsum 0) collect `(,headings ,tmsum) into lst
             finally return lst))))))

(defun org-dblock-write:nagora-report (params)
 "Fill in a dynamic timesheet reporting block."
  (let* ((buffer (plist-get params :buffer))
     (day (symbol-name (plist-get params :day)))
     (tstart (if (string-match-p "^[0-9]\\{4\\}-[0-9]\\{2\\}-[0-9]\\{2\\}$" day)
             day
           (error "Error: day format must be in YYYY-mm-dd format")))
     (tend (concat day " 23:59"))
     (table (dfeich/org-clock-hourly-report
         (dfeich/org-clock-get-tr-for-ivl buffer tstart tend)
         tstart tend)))
    (insert (format "#+CAPTION: timesheet for day %s\n" day))
    (insert "|Time|Customer| Task |Minutes|\n|------\n")
    (cl-loop
     for item in table
     do (let ((ivl (car item))
          (entries (cadr item)))
      (cl-loop for e in entries
           do (let ((headings (car e))
                (minutes (cadr e)))
            (insert (concat
                 "|"
                 (format-time-string "%H:%M" (seconds-to-time
                                  (car ivl)))
                 "-"
                 (format-time-string "%H:%M" (seconds-to-time
                                  (cadr ivl)))
                 "|" (nth 1 headings)
                 "|" (car (last headings))
                 "|" (format "%d" minutes)
                 "|\n"))))))
    (insert "|----\n|TOTAL||||\n#+TBLFM: @>$>=vsum(@[email protected])")
    (search-backward "Time")
    (org-table-align)
    (org-table-recalculate '(16))))

注:このソリューションは、org-clock-sum コードに触発されており、完全なorgパーサーを呼び出さないように選択した関数に類似していますが、ヘッドラインとクロックラインだけに興味があります。

regexp検索関数は、見出しや時刻の時間範囲に一致する "or"の正規表現を含む org-clock-sum からコピーされた興味深い概念を使用します。この考え方は、このように単一の正規表現を持つ単純な状態マシンを実装できるので、良い考えです。

5
追加された
@Bobias:私はプロファイリングしていない、それは正常なファイルのためのパフォーマンス上の大きなことではないかもしれないことができます。興味深いキャッシング機構を調べる必要があります。私は、私が1年から2年以上の時計情報を蓄積している項目を持つorg文書を持っている私自身の使い方のために、私がやったやり方で関数を書いた。クロック時間は最新のクロック間隔から最古のクロック間隔に進んでいるので、全体の解析ではなく、目標の時間間隔ではなくなった時計に到達すると、解析を停止することができます。
追加された 著者 Ross,
@tobiasとnagora:ありがとうございました。私は、Tobiasが数多くの素敵な追加をしたことに気付きました。 1時間以内の同じタスクの合計。私はまた、私の投稿を編集して、ここでStackExchangeでelispコードを正しくマークアップする方法を学びました。ありがとう!
追加された 著者 Ross,
orgパーサーはキャッシュを使用して動作し、あまりにも大きなパフォーマンスの低下を招かないはずです。キャッシングがどれくらいの距離に達しているかは確認しなかった。インスタンスの場合:私は、orgにcedet/wisentのような部分パーサがあるかどうかわかりません。このようなパーサパーサーを使用すると、一部のパーサーが編集されている場合は、ドキュメント全体を再解析する必要はありません。
追加された 著者 Mike Spivey,
私はあなたのバージョンで同じ時間に同じプロジェクトの議事録を集計し、これを私のものに合わせて調整しました。ありがとう。異なるプロジェクトの時計アイテムは、互いに対してソートされません。したがって、私はまずすべてを収集し、次にw.r.tを並べ替えます。時計の範囲の始まり。ソートにはn * log(n)のコストがあり、他のすべてのコストはn次のコスト(解析する)になります。私はソートされたリストに取り組んでいます。私はその時間に終了する作業項目を却下する。実際に作業項目がある場合にのみ時間を増やし、次の時間として(残りの)リストの最初の項目の時間をとります。
追加された 著者 Mike Spivey,
ありがとう。富の恥ずかしさ。木曜日に、私たちは開発チーム全体がフォーマットに不平を言うが、彼らは揺れることはないと経営陣と会見した。
追加された 著者 Shreemay Panhalkar,
@dfeich私は、あなたが私が比較的マイナーだったいくつかの他のニーズに合うようにTobiasのコードを変更するほうが簡単であることを発見したので、あなたにチックを与えています。それは私に多くの無意味な努力を救った。ありがとう。
追加された 著者 Shreemay Panhalkar,

次のコードで定義されている org-time-sheet コマンドは、あなたが指定したほぼ行います。 M-x org-time-sheet でインタラクティブに呼び出すと、開始時刻と終了時刻を設定することもできます。この時間範囲で開始するクロックエントリのみがタイムシートに含まれます。

ほぼ」の語句:

  1. You did not specify how you differentiate between efforts on different days. org-time-sheet writes the date in the first column when it starts a new day.
  2. It is better to write out an org-table instead of inserting commas or tabs as separators. You can then put point into the table and call the menu-point Tbl -> Export to export to whatever format is supported (e.g., csv-format).
  3. Currently, I also insert a start and a end timestamp into the first two columns of the table. This makes easier for you to check whether you get what you want. When you believe that you get what you want you can customize the function org-time-sheet-time-formatter. Just remove the formatted minutes-start and minutes-end.

編集:

  1. 同じ時間に同じプロジェクトのタイムスパンがデフォルトで合計されます。プレフィックスargを指定して org-time-sheet をコールすると、これらのタイムスパンは別々に表示されます。
  2. org-time-sheet を対話形式で呼び出すと、タイムシートがポイントに挿入されます。以前はタイムシートが次のコードブロックの後に挿入されていました。
(defcustom org-time-sheet-date-formatter
  (lambda (day month year) (format "%4d-%02d-%02d" year month day))
  "Function to format date in time sheets.
It takes three numbers as arguments: day month year."
  :type 'function
  :group 'org-clock)

(defcustom org-time-sheet-time-formatter
  (lambda (start end hour minutes headings)
    (list (format-time-string "%F %R" (apply 'encode-time minutes-start))
          (format-time-string "%F %R" (apply 'encode-time minutes-end))
          (format "%2d00--%2d00" hour (1+ hour)) (or (nth 1 headings) "") (or (nth 2 headings) "") minutes))
  "Callback function returning one table line in a time sheet (as list).
The arguments of the function are:
START:    start time with format as in `decode-time'
END:     end time with format as in `decode-time'
MINUTES:  number of minutes between start time and end time
HEADINGS: the heading titles of the current entry and all its parents as a list starting with the top-parent."
  :type 'function
  :group 'org-clock)

(eval-when-compile
  (require 'cl-lib))
(require 'org-element)
(require 'ob-core)

(defun org-element-parent (element &optional type)
  "Get parent of ELEMENT or nil if there is none.
If TYPE is non-nil get next parent of that type."
  (let* ((props (cadr element))
         (parent (plist-get props :parent)))
    (if type
        (when parent
          (if (eq (car parent) type)
              parent
            (org-element-parent parent type)))
      parent)))

(defun org-element-timestamp-less-p (ts1 ts2 &optional end)
  "Non-nil if timestamp TS1 is less than timestamp TS2.
TS1 and TS2 is timestamp data as returned by `org-element-timestamp-parser'.
If end is non-nil the end-time of TS1 and TS2 is compared else the start time."
  (cl-assert (eq (car ts1) 'timestamp) "TS1 is not a timestamp")
  (cl-assert (eq (car ts2) 'timestamp) "TS2 is not a timestamp")
  (let ((p1 (cadr ts1))
    (p2 (cadr ts2))
    (tests '("year" "month" "day" "hour" "minute"))
    ret)
    (while (and (let* ((what (intern-soft (concat ":" (car tests) (if end "-end" "-start"))))
               (t1 (plist-get p1 what))
               (t2 (plist-get p2 what)))
          (cond
           ((< t1 t2)
            (setq ret t)
            nil)
           ((= t1 t2) t)))
        (setq tests (cdr tests))))
    ret))

(defun time-day-month-year (time)
  "Return the list (day month year) from TIME.
TIME may be the time as returned by `current-time' or by `decode-time'."
  (if (<= (length time) 4)
      (setq time (decode-time time)))
  (mapcar (lambda (el) (nth el time)) '(3 4 5)))

(defun org-element-timestamp-to-time (timestamp &optional start/end encode)
  "Convert start or end of TIMESTAMP returned by `org-element-timestamp-parser'
to time format as defined in the documentation of `decode-time'.
START/END is either the symbol 'start or 'end or nil which is equivalent to 'start.
If ENCODE is non-nil the return value is encoded as described in the documentation for `current-time'."
  (cl-assert (eq (car timestamp) 'timestamp) "Argument is not a timestamp")
  (unless start/end (setq start/end 'start))
  (let* ((p (cadr timestamp))
     (ret (append
           '(0)
           (mapcar (lambda (what) (plist-get p (intern-soft (concat ":" what "-" (symbol-name start/end))))) '("minute" "hour" "day" "month" "year"))
           (list 0 nil (car (current-time-zone))))))
    (if encode
    (apply #'encode-time ret)
      ret)))

(defmacro decoded-time-complete-timezone (t1 t2)
  "If only one of the time specifications T1 and T2 has time-zone information
append that to the other one."
  `(let ((n1 (length ,t1))
         (n2 (length ,t2)))
     (cond
      ((> n1 n2)
       (setq ,t2 (copy-sequence ,t2))
       (setf (nthcdr n2 ,t2) (nthcdr n2 ,t1)))
      ((< n1 n2)
       (setq ,t1 (copy-sequence ,t1))
       (setf (nthcdr n1 ,t1) (nthcdr n1 ,t2))))))

(defun decoded-time-less-p (t1 t2)
  "Like `time-less-p' but for decoded time values as `decode-time' returns."
  (decoded-time-complete-timezone t1 t2)
  (time-less-p (apply 'encode-time t1) (apply 'encode-time t2)))

(defun decoded-time-advance (time dt)
  "Return TIME advanced by DT but for decoded time values as `decode-time' returns.
The time zone information of time is used for the result."
  (decode-time (apply 'encode-time (append (cl-mapcar #'+ (butlast time (- (length time) 6)) (butlast dt (- (length dt) 6))) (nthcdr 6 time)))))

(defun org-time-sheet (&optional tStart tEnd dont-sum)
  "Create time sheet for time span from tStart to tEnd from current org buffer.
When called non-interactively each of the parameters tStart and tEnd may be nil
or must be decoded time (see `decode-time').
Do not sum up minutest of a project within an hour if dont-sum is non-nil.
Interactively do not sum if called with prefix arg."
   (interactive (list
                 (decode-time (org-read-date t t nil "Start time:" '(0 0)))
                 (decode-time (org-read-date t t nil "End time:"))
         current-prefix-arg))
   (org-time-sheet-shedule (org-time-sheet-collect tStart tEnd) (called-interactively-p 'any) dont-sum))

(defun org-time-sheet-collect (tStart tEnd)
  "Returns ordered time sheet collection of current buffer
for clocked items with start time within the range from tStart to tEnd."
  (if (> (length tStart) 4)
      (setq tStart (apply 'encode-time tStart)))
  (if (> (length tEnd) 4)
      (setq tEnd (apply 'encode-time tEnd)))
   (let ((tree (org-element-parse-buffer)))
     (cl-stable-sort 
      (org-element-map tree 'clock
        (lambda (clock)
          ;; get the relevant data of the clocks
          (let* ((timestamp (plist-get (cadr clock) :value))
                 (parent clock)
                 (headers (nreverse (cl-loop while (setq parent (org-element-parent parent 'headline)) collect (car (plist-get (cadr parent) :title))))))
            (cl-assert timestamp nil "Clock line without timestamp")
            (when (and (or (null tStart) (null (time-less-p (org-element-timestamp-to-time timestamp 'start t) tStart)))
                       (or (null tEnd) (time-less-p (org-element-timestamp-to-time timestamp 'end t) tEnd)))
              (list (org-element-timestamp-to-time timestamp 'start)
                    (org-element-timestamp-to-time timestamp 'end)
                    headers))
            )))
      #'time-less-p
      :key (lambda (clock) (apply 'encode-time (car clock))))))

(defun org-time-sheet-shedule (clocks &optional interactive dont-sum)
  "Creates time sheet shedule from ordered time sheet clock collection (see `org-time-sheet-collect')."
     ;; sheduling
     (when clocks
       (setq clocks (cons nil clocks))
       (let* ((start (copy-sequence (caadr clocks)))
              (day-month-year (time-day-month-year start))
              (shedule (list (list (apply org-time-sheet-date-formatter day-month-year)))))
         (setf (nth 1 start) 0) ;; clear minutes
         (while (cdr clocks)
           (let ((end (decoded-time-advance start '(0 0 1 0 0 0)))
         project-alist
                 (iter clocks))
             (while (decoded-time-less-p (cl-caadr iter) end) ;; collect clocks starting before the end of current hour
               (let* ((start-time (cl-caadr iter))
                      (end-time (cl-cadadr iter))
                      (minutes-start (if (decoded-time-less-p start-time start) start start-time))
                      (minutes-end (if (decoded-time-less-p end end-time) end end-time))
              (minutes (/ (nth 1 (time-subtract (apply 'encode-time minutes-end) (apply 'encode-time minutes-start))) 60))
                      (headlines (nth 2 (cadr iter)))
              (project (assoc headlines project-alist)))
         (if (and project (null dont-sum))
             (setcdr project (list (+ (cadr project) minutes) minutes-start minutes-end))
           (setq project-alist (cons (list headlines minutes minutes-start minutes-end) project-alist)))
                 (if (decoded-time-less-p end end-time)
                     (setq iter (cdr iter))
                   ;; delete clock that also finishes in this hour:
                   (setcdr iter (cddr iter))) ;; delete clock entry
                 ))
         (setq project-alist (nreverse project-alist))
         ;; Compose shedule for hour:
         (while project-alist
           (let ((headlines (caar project-alist))
             (minutes (nth 1 (car project-alist)))
             (minutes-start (nth 2 (car project-alist)))
             (minutes-end (nth 3 (car project-alist))))
         (setq shedule (cons (funcall org-time-sheet-time-formatter minutes-start minutes-end (nth 2 start) minutes headlines) shedule)))
           (setq project-alist (cdr project-alist)))
             ;; calculate new time:
             (when (cdr clocks)
               (let ((next-hour-start-time (decoded-time-advance start '(0 0 1 0 0 0)))
                     (next-hour-end-time (decoded-time-advance start '(0 0 2 0 0 0))))
                 (setq start (copy-sequence (caadr clocks)))
                 (setf (nth 1 start) 0) ;; minutes
                 (when (decoded-time-less-p start next-hour-end-time)
                   (setq start next-hour-start-time))
                 (let ((new-day-month-year (time-day-month-year start)))
                   (unless (equal day-month-year new-day-month-year)
                     (setq shedule (cons (list (apply org-time-sheet-date-formatter new-day-month-year)) shedule)
                           day-month-year new-day-month-year)))))))
         (setq shedule (nreverse shedule))
         (when interactive
       (insert (with-temp-buffer
             (insert "#+begin_src emacs-lisp\n#+end_src\n")
             (let ((pt (point)))
               (org-babel-insert-result shedule)
               (delete-region (point-min) pt))
             (buffer-string))))
         shedule)))

あなたの例では、次のような出力が得られます。

| 2015-10-09       |                  |            |                       |                                |    |
| 2015-10-09 15:10 | 2015-10-09 16:00 | 1400--1500 | PU                    | Identify PU Open equella block | 50 |
| 2015-10-09 16:00 | 2015-10-09 17:00 | 1600--1700 | PU                    | Identify PU Open equella block | 60 |
| 2015-10-09 17:00 | 2015-10-09 17:06 | 1700--1800 | PU                    | Identify PU Open equella block |  6 |
| 2015-11-16       |                  |            |                       |                                |    |
| 2015-11-16 14:49 | 2015-11-16 15:00 | 1400--1500 | PU                    | Update UAT                     | 11 |
| 2015-11-17       |                  |            |                       |                                |    |
| 2015-11-17 09:12 | 2015-11-17 09:18 |  900--1000 | PU                    | Update UAT                     |  6 |
| 2016-01-12       |                  |            |                       |                                |    |
| 2016-01-12 11:00 | 2016-01-12 12:00 | 1100--1200 | Greenwich Consultancy |                                | 60 |
| 2016-01-12 12:00 | 2016-01-12 13:00 | 1200--1300 | Greenwich Consultancy |                                | 60 |
| 2016-01-12 13:00 | 2016-01-12 14:00 | 1300--1400 | Greenwich Consultancy |                                | 60 |
| 2016-01-12 14:00 | 2016-01-12 15:00 | 1400--1500 | Greenwich Consultancy |                                | 60 |
| 2016-01-12 15:00 | 2016-01-12 16:00 | 1500--1600 | Greenwich Consultancy |                                | 60 |
| 2016-01-12 16:00 | 2016-01-12 16:53 | 1600--1700 | Greenwich Consultancy |                                | 53 |
| 2016-01-13       |                  |            |                       |                                |    |
| 2016-01-13 14:48 | 2016-01-13 15:00 | 1400--1500 | Greenwich Consultancy |                                | 12 |
| 2016-01-13 15:00 | 2016-01-13 15:29 | 1500--1600 | Greenwich Consultancy |                                | 29 |
| 2016-01-29       |                  |            |                       |                                |    |
| 2016-01-29 12:27 | 2016-01-29 12:33 | 1200--1300 | PU                    | PSMD Block                     |  6 |
| 2016-02-02       |                  |            |                       |                                |    |
| 2016-02-02 16:39 | 2016-02-02 17:00 | 1600--1700 | PU                    | PSMD Block                     | 21 |
| 2016-02-03       |                  |            |                       |                                |    |
| 2016-02-03 09:39 | 2016-02-03 10:00 |  900--1000 | PU                    | PSMD Block                     | 21 |
| 2016-02-03 10:00 | 2016-02-03 10:24 | 1000--1100 | PU                    | PSMD Block                     | 24 |
| 2016-02-05       |                  |            |                       |                                |    |
| 2016-02-05 10:36 | 2016-02-05 10:53 | 1000--1100 | PU                    | PSMD Block                     | 17 |
| 2016-02-05 11:11 | 2016-02-05 12:00 | 1100--1200 | PU                    | PSMD Block                     | 49 |
| 2016-02-05 12:00 | 2016-02-05 12:02 | 1200--1300 | PU                    | PSMD Block                     |  2 |
| 2016-02-05 14:27 | 2016-02-05 15:00 | 1400--1500 | PU                    | PSMD Block                     | 33 |
| 2016-02-05 15:00 | 2016-02-05 16:00 | 1500--1600 | PU                    | PSMD Block                     | 60 |
| 2016-02-05 16:00 | 2016-02-05 16:36 | 1600--1700 | PU                    | PSMD Block                     | 36 |
| 2016-02-09       |                  |            |                       |                                |    |
| 2016-02-09 10:15 | 2016-02-09 10:58 | 1000--1100 | PU                    | PSMD Block                     | 43 |
| 2016-02-09 12:13 | 2016-02-09 13:00 | 1200--1300 | PU                    | PSMD Block                     | 47 |
| 2016-02-09 13:00 | 2016-02-09 13:01 | 1300--1400 | PU                    | PSMD Block                     |  1 |
| 2016-02-09 14:24 | 2016-02-09 15:00 | 1400--1500 | PU                    | PSMD Block                     | 36 |
| 2016-02-09 15:00 | 2016-02-09 15:02 | 1500--1600 | PU                    | PSMD Block                     |  2 |
| 2016-02-09 16:17 | 2016-02-09 16:31 | 1600--1700 | PU                    | PSMD Block                     | 14 |
| 2016-02-11       |                  |            |                       |                                |    |
| 2016-02-11 14:27 | 2016-02-11 14:47 | 1400--1500 | PU                    | PSMD Block                     | 20 |
| 2016-02-17       |                  |            |                       |                                |    |
| 2016-02-17 10:03 | 2016-02-17 10:16 | 1000--1100 | PU                    | Update UAT                     | 13 |
| 2016-02-18       |                  |            |                       |                                |    |
| 2016-02-18 10:40 | 2016-02-18 11:00 | 1000--1100 | Greenwich Consultancy |                                | 20 |
| 2016-02-18 11:00 | 2016-02-18 11:10 | 1100--1200 | Greenwich Consultancy |                                | 10 |
| 2016-02-25       |                  |            |                       |                                |    |
| 2016-02-25 11:19 | 2016-02-25 11:33 | 1100--1200 | PU                    | UAT PSMD Roamers problem       | 14 |
| 2016-02-25 16:56 | 2016-02-25 16:59 | 1600--1700 | PU                    | Server tidy                    |  3 |
| 2016-02-25 16:59 | 2016-02-25 17:00 | 1600--1700 | PU                    | Server tidy                    |  1 |
| 2016-02-25 17:00 | 2016-02-25 18:00 | 1700--1800 | PU                    | Server tidy                    | 60 |
| 2016-02-25 18:00 | 2016-02-25 19:00 | 1800--1900 | PU                    | Server tidy                    | 60 |
| 2016-02-25 19:00 | 2016-02-25 20:00 | 1900--2000 | PU                    | Server tidy                    | 60 |
| 2016-02-25 20:00 | 2016-02-25 21:00 | 2000--2100 | PU                    | Server tidy                    | 60 |
| 2016-02-25 21:00 | 2016-02-25 22:00 | 2100--2200 | PU                    | Server tidy                    | 60 |
| 2016-02-25 22:00 | 2016-02-25 23:00 | 2200--2300 | PU                    | Server tidy                    | 60 |
| 2016-02-25 23:00 | 2016-02-26 00:00 | 2300--2400 | PU                    | Server tidy                    | 60 |
| 2016-02-26       |                  |            |                       |                                |    |
| 2016-02-26 00:00 | 2016-02-26 01:00 |  000-- 100 | PU                    | Server tidy                    | 60 |
| 2016-02-26 01:00 | 2016-02-26 02:00 |  100-- 200 | PU                    | Server tidy                    | 60 |
| 2016-02-26 02:00 | 2016-02-26 03:00 |  200-- 300 | PU                    | Server tidy                    | 60 |
| 2016-02-26 03:00 | 2016-02-26 04:00 |  300-- 400 | PU                    | Server tidy                    | 60 |
| 2016-02-26 04:00 | 2016-02-26 05:00 |  400-- 500 | PU                    | Server tidy                    | 60 |
| 2016-02-26 05:00 | 2016-02-26 06:00 |  500-- 600 | PU                    | Server tidy                    | 60 |
| 2016-02-26 06:00 | 2016-02-26 07:00 |  600-- 700 | PU                    | Server tidy                    | 60 |
| 2016-02-26 07:00 | 2016-02-26 08:00 |  700-- 800 | PU                    | Server tidy                    | 60 |
| 2016-02-26 08:00 | 2016-02-26 09:00 |  800-- 900 | PU                    | Server tidy                    | 60 |
| 2016-02-26 09:00 | 2016-02-26 09:22 |  900--1000 | PU                    | Server tidy                    | 22 |
| 2016-02-26 15:35 | 2016-02-26 16:00 | 1500--1600 | PU                    | Gradebook problem              | 25 |
| 2016-02-26 16:00 | 2016-02-26 16:26 | 1600--1700 | PU                    | Gradebook problem              | 26 |
| 2016-02-26 16:26 | 2016-02-26 16:53 | 1600--1700 | PU                    | PSMD Block                     | 27 |
5
追加された
@Nagora私は、この質問よりももっと洗練された解決策があるかどうかを知るために、この質問を可能な限り開いたままにすることを提案します。解決策として受け入れることができ、私の解決策が私に何らかの仕事をもたらしたとしても<�私が学ぶことができる>エレガントな3ライナーを得ることができれば非常にうれしいです。それにもかかわらず、誰も何かより良いものが出てこない場合は、少なくともこのモンスターを持っている;-)。
追加された 著者 Mike Spivey,
うーん、 "サーバチルド"を正しく閉じていないようだ。とにかく、これは素晴らしいものです。私はコードの量に驚いていますが、少なくとも私はそれを自分で解決していないという馬鹿感は感じません。私はそれにいくつかのテストランを与え、私がどのようにして得るかを見ていきます。どうもありがとう。
追加された 著者 Shreemay Panhalkar,
ありがとうございましたが、コードを扱いやすくしたので、私はもう1つ答えました。とにかく努力してくれてありがとう。
追加された 著者 Shreemay Panhalkar,