タスク管理の再検討(5) タスク実行時間の記録 : Notion 解説(55)

1. はじめに

タスク管理の構築途中でしたが、Twitter の話題から NotionTimeRecording というショートカットを作成しました。作ってみたところ、自分の用途にもピッタリなので今回のタスク管理に組み入れることにしました。

2. タスク管理の流れ

タスクはこんな感じでタスクデータベースに入ります。

  1. Google のカレンダーに手動登録 → GAS で Notion タスクデータベースに登録 (カレンダーデータのデータベースへの一括登録 (Notion API 編): Notion 解説(18) - hkob’s blog)
  2. Outlook のカレンダーに誰かが会議を登録 → Microsoft PowerApps (Outlook の会議召集連絡から Notion タスクを登録 : Notion 解説(25) - hkob’s blog)
  3. macOS の Alfred にタスク名と日付・時間を登録 → API で Notion と Google カレンダーに同時登録 (タスク作成時にカレンダーにも同時設定 : Notion 解説(33) - hkob’s blog)
  4. 授業や試験の時間割を ics からカレンダーアプリに登録 → カレンダーから Google カレンダーに連携 → 1 の機能で登録
  5. 今から始めるタスクを NotionTimeRecording で作成 → ショートカットが開始時間を設定した Notion タスクを作成(NotionTimeRecording の作成 : Notion 解説 (53) - hkob’s blog)

今回は、最後の 5 が大きいですね。3回のアクションでタスクが生成され、Notion のページが開きます。作業内容を開いた Notion ページに記録できるのがいいですね。タスクが完了したら、再度 NotionTimeRecording でタスクを選択すると、自動的に終了時間が記録され、タスクが完了になります。当初、iOS の背面タップを想定していましたが、macOS のサービスから呼び出した方が簡単なので、今はこっちがメインになっています。

これまで、タスクには実施したポモドーロ数を記録していました (Alfred からポモドーロプロパティを追加 : Notion 解説(29) - hkob’s blog)。 当初はちゃんと記録していたのですが、だんだん面倒になって記録しなくなっていました。今回、NotionTimeRecording で時間記録ができるようになったので、こちらをメインに記録対応することにしました。そんなわけで、タスクにかかった時間をタスクデータベースのフォーミュラで計算するようにしたのが、この記事です。

単純に分だけだとわかりにくいので、HH:MMの形式の文字列も作成しています。

時間範囲の計上

3. 今日のタスクへの実施時間の転記

せっかくタスクデータベースに実施時間が入ったのですが、今日のタスクの To Do は単にタスクページへのリンクがあるだけなので、この実施時間は見えません。そこで、終了タスクに対して実施時間を転記することを考えました。前回の記事でタスクデータベースと完了チェックの同期ができているので、その続きとして完了タスクに対して、実施時刻を追記するスクリプトを記述します。

hkob.hatenablog.com

3.1 今日の完了タスクを取得するメソッド

NotionTimeRecording で登録したタスクは、今日急遽入れたタスクなので To Do ブロックには登録されていません。これまでの処理で、完了してしまっているタスクについては無視する処理をしていたので、どちらにしても To Do には転記されていないことになります。ここでは、今日の完了タスクのみを抽出することで、これらのタスクに対応することにします。

# @param [NotionRubyMapping::Database] db タスクデータベース
# @param [Date] today 今日の日付
# @return [NotionRubyMapping::List] タスクページのリスト
def today_finished_tasks(db, today)
  dp = db.properties["日付"]
  cp = db.properties["Done"]
  query = cp.filter_equals(true).and(dp.filter_equals(today)).ascending dp # クエリを準備
  db.query_database query # 今日までの未完了のタスクを古い順に取得
end

ここでタイムゾーンの問題に気づきました。Notion API の Date プロパティのクエリについては UTC 固定での検索となっています。日本は9時間しかずれていないので、朝9時までのタスクはあまりなく、これまで気づいていませんでした。今回、朝5時に実施したタスクが抽出できないことでこの問題に気づきました。結局、NotionRubyMapping の filter_equals, filter_does_not_equal にしてはタイムゾーンを含めた時間範囲で検索するようにライブラリを修正することで対応しました。ツール側では上に書いたように何も気にせず、filter_equals を使えばいいです。

3.2 実施時間を打刻するメソッド

ここでは、ページ属性の「実施時間(表示)」プロパティから時間文字列を取得します。formula なので「string」属性で取得できました。すでに To Do ブロックに設定されていれば、タスクを完了にした上で実施時間を打刻します。重複して追記しないように文字列の最後がページへのメンションオブジェクトだった時だけ、文字列を追加するようにしています。

NotionTimeRecording で作ったタスクなどは、To Do ブロックに入っていないので、else 以下の処理で新規の To Do ブロックを追加しています。

# @param [NotionRubyMapping::SyncedBlock] sb_org オリジナル同期ブロック
# @param [Array<NotionRubyMapping::Page>] tasks # タスク一覧の配列
# @param [Hash<String=>NotionRubyMapping::ToDoBlock, String>] td_hash タスクページと To Do ブロックのハッシュ
def append_exec_time(sb_org, tasks, td_hash)
  tasks.each do |task|
    time_str = task.properties["実施時間(表示)"].formula["string"]
    if (to_do = td_hash[task.id]) # すでに To Do Block に登録済み
      unless to_do.checked
        to_do.checked = true # To Do ブロックがチェックされていなければチェック
        to_do.save
      end
      rta = to_do.rich_text_array
      if rta[rta.count-1].is_a? MentionObject # To Do Block の最後の文字列がメンションページだったら
        to_do.rich_text_array << time_str
        to_do.save
      end
    else # 未登録の場合には新規作成
      mb = MentionObject.new "page_id" => task.id, "plain_text" => task.title
      sb_org.append_block_children ToDoBlock.new([mb, time_str], true)
    end
  end
end

3.3 メイン側に処理を追加

メイン側では上記二つのメソッドを呼び出すだけです。

#### 8. 今日の完了タスクに実施時間を追加
finished_tasks = today_finished_tasks(et_database, today)
append_exec_time(synced_block_original, finished_tasks, todo_hash)

完成したものがこちらです。


www.notion.so