Todoistでタスクにかかる時間を見積もって完了時刻計算する方法【追記あり】

Todoistでタスクの見積もり時間を計算してタスクシュート風に使う方法

「今日やりたいことが全部出来なかった…」

という事を何回も思うことがあるのであれば、それは「できるはずのないタスクの詰め方をしている」と思ったほうがいいかもしれません。

僕は「タスクシュート」というタスク管理の考え方を知ってから「タスクがこなせなかった…」と思うことがほとんどなくなりました。

その「タスクシュート」の考え方を僕も愛用している人気タスク管理アプリ「Todoist」でも使いたいと思い、ラベルとブックマークレットを使って実現する方法を考えついたので共有したいと思います!

タスクシュートにWEB版が登場!(2016/08/08 追記)

本家タスクシュートのWEB版である「TaskChute Cloud」が登場しました!

こちらも要チェック!

タスクシュート(TaskChute)の考え方をTodoistでも

タスクシュートに出会った衝撃

タスクシュートと出会って衝撃を受けた

まず最初にTodoistでタスクの時間見積りと終了時刻を計算するブックマークレットを作ろうと思ったきっかけからお話しします。

「タスクシュート」の考え方にどっぷり浸かっています。よっひー(@yosiakatsuki)です。

僕が「タスクシュート」というものに興味を持ったのは2015年の年始。

ちょうど仕事が忙しくなり、「これじゃマズイ」と、タスク管理とか「ライフハック」に興味を持ち始めて、次の本を読んだ事がきっかけでした。

元々「タスク管理」なんて真剣に考えたことがなかった僕なので、この本を読む前と後では仕事の進め方がガラッとかわるきっかけになりました。

タスクにかかる時間を見積もって、全て完了する時刻を算出する

タスクにかかる時間を見積り、終了時刻を計算する

先に紹介した書籍の中で「タスクシュートの5つの基本」として紹介されていることがあるのですが、タスク管理初心者の僕でもその中から次の2点はすぐに実行するようになりました。

  • 全てのタスクの見積時間を出しておく
  • 見積もり時間から今日1日の終了時刻を算出する

本来ならば、「TaskChute2」というツールを使うと楽なのだと思うのですが、会社のルールとして外部ツールを簡単には使えませんでした…

幸いにも僕はVB.NETのプログラマだったのでExcelVBAを駆使して「それっぽい物」を自作して使っていました。

上の2点を実践するようになってから、「この見積もり通りに進めればこの時間には帰れる!」と、いいモチベーションを保って仕事を進められたり、

「いま脱線したら帰りが遅くなる…」と、自制する為のきっかけにもなり、脱線も少なくなって、ほぼほぼ帰りたい時間に帰れるようになりました。

1日に遂行可能なタスクのリストアップをする

タスクのリストアップをする

モチベーションを保つ事も重要ですが、それよりも「物理的に無理なタスクの詰め方をしなくなった」事が大きな効果を生んでいると思います。

例えば「『今日やりたいこと』としてリストアップしたタスクの見積もり時間を積み上げたら11時間かかることがわかった」とします。

「11時間かかる」ということがわかれば、明らかに3時間は残業が必要になるので、この時点で「今日じゃなくても間に合うタスク」を明日以降にまわす判断が出来ます。

(就業時間を8時間として考えています)

1日(8時間)に物理的にできることをリストアップすることで「全然終わらない…」「今日やりたいことが全部出来なかった…」といった事が以前に比べて圧倒的に少なくなりました。

1日に使える時間は決まっているので、どう頑張ってもそれ以上かかるタスクはできないんです。

タスクにかかる時間を意識するって大事です。

「見積もり時間」と「完了時刻」をTodoistでも!

「見積もり時間」と「完了時刻」をTodoistでも!

ここからようやく本題が見えてくるわけですが…(前フリが長くてスミマセン)

ブログきっかけで転職する前の職場では便利なツールを使うチャンスがありませんでした…

なので、とりあえず仕事には関係のない個人的なタスクをiPhoneから登録するというのが今までの僕のTodoistの使い方でした。

今ではいろいろとツールを使う事ができるので、タスクシュートを使おうとも考えたのですが…

使い慣れたTodoistからいまさら離れられるわけもなく、「タスクシュート」というタスク管理の考え方から学んだ

  • 「タスクにかかる時間を見積もる」
  • 「1日の終了時刻を把握する」
ということを使い慣れたTodoistでもやってみようじゃないか!

ということで、タスクにかかる時間の見積り時間はラベルを活用して、1日の終了時刻の計算はブックマークレットを使う方法を考えついたのでその方法について紹介したいと思います!

あくまでも「タスクシュート風」

「風」という言葉は便利なもので…言い換えれば「タスクシュートっぽく使う」になると思います。

全てを「タスクシュート」に合わせることは不可能ですので、Todoistの仕様と自分のタスク管理のやりやすい方法に合わせているだけです。

あまり期待し過ぎるとがっかりしてしまうかもしれません。あしからず。

タスクシュートについては下記のサイトをみると参考になると思います。

Todoistをタスクシュート風に使う方法

Todoistをタスクシュート風に使う方法の全体概要

ざっと「Todoistをタスクシュート風に使う方法」の概要を説明します。

まず、タスクの見積り時間についてはTodoistのラベル機能を活用しています。

見積り時間用のラベルを作り、タスクに設定していきます。

タスクにセットした見積もり時間から1日の終了時刻を計算するのはブックマークレットで行います。

ブックマークレットを使う事になるので、TodoistはアプリではなくWEB版を使うことになります。

ほんとにざっくりとした説明は以上です。続いて、僕が実践しているラベルの設定方法と共に、ブックマークレットの使い方を説明します。

タスクの見積もり時間のラベルでの表現方法

Todoistのラベルにタスクの見積り時間を表現するラベルを作る

まず、タスクの見積り時間となるラベルですが、僕は上の画像の青色のようなラベルを作って管理しています。

ラベルの先頭にスラッシュを2つつけたラベルの塊がタスクの見積り時間用で、単位は「分」になっています。(「//60」なら60分かかるタスク)

個々のタスクにつけるラベルは最長でも60分のものをつけるようにしています。

60分以上かかる場合は、60分以下で完了できる作業にタスクを細かく分解して登録します。

「最長60分」の理由は、Sunriseに連携した時にSunrise側でのタスクの表示が60分になるからです。

一応60分以上のラベルもあるのですが、これは打ち合わせなど分解のしようがないタスクにつけます。

長い時間のラベルは「120分(2時間)」と「240分(4時間)」しか準備していませんが、3時間かかる打ち合わせでは「120分」と「60分」の2つのラベルをつけるようにして、ラベルの種類を増やさないようにしています。

完了時刻を計算するブックマークレット

※ブックマークレットの設定方法は後述します。

ラベルで見積り時間を設定したら1日の完了時刻を計算します。

手計算は非常に面倒なことになるので、多少力技なコードになっていますが、次のようなブックマークレットを作りました。

(※次の7日間に対応した最新版ブックマークレットがあります。そちらをご確認ください)

javascript:!function(d,f,s){s=d.createElement("script");s.src="//j.mp/1bPoAXq";s.onload=function(){f(jQuery.noConflict(1))};d.body.appendChild(s)}(document,function($){$('#mtime-outer').remove();$('body').append('<div id="mtime-outer" style="position:fixed;bottom:0;right:0;padding:20px;background-color:#eee;"><p>フィルタ:<select id="filter" style="background-color:#FFF;"><option value="ALL">ALL</option></select></p><p>開始時間:<input type="checkbox" name="chkstime" id="chkstime" /><input type="time" name="starttime" id="starttime" value="09:30" disabled /></p><p>見積時間:<span id="mtime-hour"></span>h (<span id="mtime"></span>m)</p><p style="font-weight:bold;">完了見込:<span id="kantime"></span></p></div>');function mjikan(){i=0;j=0;inttime=0;fselect=$('#filter').val();tlist=$('.task_item:not(.checked,.history_item)');dlist=tlist.find('.div_due_date .date');$('#filter').children().remove();$('#filter').append($('<option></option>').val('ALL').text('ALL'));for(j=0;j<dlist.length;j++){lval=$(dlist[j]).text().replace(/\d\d:\d\d /g,'');if(lval!=''&&$('#filter .'+lval).length==0){$('#filter').append($('<option></option>').attr('class',lval).val(lval).text(lval))}}$('#filter').val(fselect);for(j=0;j<tlist.length;j++){if(fselect=='ALL'||$(tlist[j]).find('.div_due_date .date').text().indexOf(fselect)!=-1){llist=$(tlist[j]).find('.label:not(.label_sep)');for(i=0;i<llist.length;i++){strlbl=$(llist[i]).text().replace('//','').replace('_','.');if($.isNumeric(strlbl)){inttime+=parseInt(strlbl,10)}}}}$('#mtime').text(inttime);$('#mtime-hour').text((inttime/60).toFixed(1));var date=new Date();if($("#starttime").val()!=""&&$('#chkstime').prop('checked')){date=new Date(date.toDateString()+' '+$("#starttime").val());}date.setMinutes(date.getMinutes()+inttime);$('#kantime').text(date.getHours()+':'+('0'+date.getMinutes()).slice(-2));};$('#chkstime').on('change',function(){if($('#chkstime').prop('checked')){$('#starttime').removeAttr("disabled");}else{$('#starttime').attr("disabled", "disabled");}mjikan();});mjikan();setInterval(mjikan, 1000);$('#filter').change(mjikan);})
Todoistをタスクシュート風に使うブックマークレットを実行する

TodoistのWEB版を開いてブックマークレットを実行すると、ページの右下に、画像のような見積もり時間の合計と1日の終了時刻(完了見込)が表示されます。

タスクの完了見込は現在時刻に見積時間を足して計算しています。

これは、Todoistでは完了したタスクは表示されなくなる為、「残りのタスクを今からやったら何時に終わるか」という考え方で計算する必要があるからです。

もし、翌日以降のタスクを組む場合などは、見積時間の上にある「開始時間」のチェックボックスにチェックを入れて開始時刻を入力します。

そうすることで、入力した時刻からタスクを実行して完了する時刻を知ることが出来るので、「朝からタスクをこなして何時に終了するか」を見る事ができます。

予定を組む場合に使用するブックマークレットのフィルタ機能

ブックマークレットを実行すると出てくる見積もり時間等を表示するエリアの一番上にある「フィルタ」は日別のタスクの見積り時間合計を見る為に使います。

例えば、Todoistのタスクの検索で「!日付なし」と検索すると、期限の割あたっているタスクがすべて一覧に表示されます。

この一覧の中から「明日は何時間タスクを入れてたっけ?明後日は?」と、日毎のタスクの見積り時間を見ていく為に「フィルタ」の項目を使います。

フィルタの項目に日別の期日がセットされる

デフォルトでは「ALL」になっていますが、リストを開くと、今表示しているタスクの一覧の中にある期限日が表示されます。

フィルタを操作して日毎の見積り時間を再計算させる

リストから見積もり時間を知りたい日を選ぶと、タスクの見積り時間が選んだ日付のものになり、合わせて完了見込の表示も変わります。

僕がこの機能は仕事のタスクを入れる時に使います。

例えば、1周間くらいで1本プログラムを作らなければならない時、「Work」プロジェクト内にプログラムが完成するまでの作業工程を分解して、見積もり時間を設定しつつタスクに登録します。

そして、フィルタを「今日」「明日」と変えて、定時時間内でどれだけタスクをこなせるか確認しながらタスクの期限を切る…そんなふうに使っています。

注意事項として、プロジェクト毎の表示の時にうまく機能するように作っているので、「次の7日間」の表示では使えないです。スミマセン。

ブックマークレットはオレオレ仕様です。ご了承下さい。

本来なら、もう少しブックマークレットの機能をブラッシュアップしてから公開しようと思ったんですけど…(フィルタ項目のソートとか…)

意外とこのブックマークレットについてのツイートの反響があったのと、正直「これ以上機能盛り込んでもあまり自分の生産性向上には繋がらないかな」と思って公開に踏み切りました。

もし、改造してもっと使いやすいブックマークレットが出来ましたら教えていただきたいです!(特に「次の7日間」とか!!)

とは言え、「ブックマークレットを作ること」「ブックマークレットを使うこと」が目的ではないので今のままでも十分な気がしてます。

自分のスタイルに合わせてお使いください。

次に、ちょっとしたブックマークレットの設定方法を説明します。

Todoistのタスクの見積もり時間を計算するブックマークレットの設定方法

開始時間の設定方法

ブックマークレット開始時間を変更する

開始時間はブックマークレットの中に「09:30」と書かれている部分がありますので、その部分をご自身の行動開始時間に合わせて変更して下さい。

僕の場合、このブックマークレットは仕事が終わる時間を計算するために使っているので、会社の始業時間に合わせて時刻設定しています。

僕と同じく仕事のみで使う場合は会社の始業時間に合わせると1日の仕事が終わる時間、つまり、帰れる時間を「完了見込」として知ることができるようになります。

8時半なら「08:30」、10時なら「10:00」という感じに、時間2桁・分2桁で登録して下さい。

見積もり時間を表現するラベルの設定

ブックマークレットでは「//60」のように、スラッシュ2つと数字をラベルに登録してタスクの見積もり時間を表現しています。

ブックマークレットではこのスラッシュ2つを削除して、数字の部分だけを取り出すようにして見積時間の積み上げ計算をしています。

ブックマークレットの見積もり時間設定を変更する

基本的には同じ感じでラベルを作っていただくのが一番楽ですが、スラッシュ以外を使う場合は上の黄色くハイライトしたスラッシュ2つが書かれた部分を変更する必要があります。

書式によっては簡単な修正では済まない場合があるので「どうしても」という場合はTwitterで相談して頂ければと思います。

(なるべく頑張りますが、すぐ返事できるとは限らないです…)

1日の終り時間がわかるとすっきりする!

このブックマークレットはやっぱり作ってよかったですね!

予定を組んだ時に1日の終り時間がわかって、ダラダラすればするほど帰れる時間が遅くなるのが目に見えてわかるので、いい感じで集中力が保てますし、、

前倒しで進められれば「自分、いい感じで進められてる!」という励みにもなります!

後は、「行動のログをとって振り返る」ということが重要になるのですが、これまた記事にするのがやや大変なのでまた後で紹介したいと思います。

【2015/10/01追記】次の7日間に対応しました。

「次の7日間」のように、日付ごとにタスクの一覧が出るタイプの表示での見積もり時間の計算について要望が多かったので、対応しました。

相変わらずのゴリ押しコードですが、一応動いております。

Todoistで見積り時間を計算するブックマークレットで次の7日間に対応

「次の7日間」のように、日付が見出しになっていてその下にその日のタスクが表示される一覧でもフィルタ項目で日毎の絞り込みができるようになりました。

以下のブックマークレットをご使用下さい(変更前のものも一応どこかにコピーして保存しておくことをおすすめします)。

javascript:!function(d,f,s){s=d.createElement("script");s.src="//j.mp/1bPoAXq";s.onload=function(){f(jQuery.noConflict(1))};d.body.appendChild(s)}(document,function($){$('#mtime-outer').remove();$('body').append('<div id="mtime-outer" style="position:fixed;bottom:0;right:0;padding:20px;background-color:#eee;"><p>フィルタ:<select id="filter" style="background-color:#FFF;"><option value="ALL">ALL</option></select></p><p>開始時間:<input type="checkbox" name="chkstime" id="chkstime" /><input type="time" name="starttime" id="starttime" value="09:30" disabled /></p><p>見積時間:<span id="mtime-hour"></span>h (<span id="mtime"></span>m)</p><p style="font-weight:bold;">完了見込:<span id="kantime"></span></p></div>');function mjikan(){mode=0;i=0;j=0;inttime=0;fselect=$('#filter').val();tlist=$('.task_item:not(.checked,.history_item)');dlist=tlist.find('.div_due_date .date');if(!dlist.length&&$('.h2_date').length>1){dlist=$('.h2_date');mode=1;}$('#filter').children().remove();$('#filter').append($('<option></option>').val('ALL').text('ALL'));for(j=0;j<dlist.length;j++){lval=$(dlist[j]).text().replace(/\d\d:\d\d /g,'');ltext=lval;if(mode==1){ltext=$(dlist[j]).prev('a').text()}if(lval!=''&&$('#filter .'+lval).length==0){$('#filter').append($('<option></option>').attr('class',lval).val(lval).text(ltext))}}$('#filter').val(fselect);if(!$('#filter').val()){$('#filter').val('ALL')}if(mode==1&&fselect!='ALL'){for(k=0;k<dlist.length;k++){if($(dlist[k]).text()==fselect){tlist=$(dlist[k]).closest('div').next('ul').find('.task_item:not(.checked,.history_item)');}}fselect='ALL';}for(j=0;j<tlist.length;j++){if(fselect=='ALL'||$(tlist[j]).find('.div_due_date .date').text().indexOf(fselect)!=-1){llist=$(tlist[j]).find('.label:not(.label_sep)');for(i=0;i<llist.length;i++){strlbl=$(llist[i]).text().replace('//','').replace('_','.');if($.isNumeric(strlbl)){inttime+=parseInt(strlbl,10)}}}}$('#mtime').text(inttime);$('#mtime-hour').text((inttime/60).toFixed(1));var date=new Date();if($("#starttime").val()!=""&&$('#chkstime').prop('checked')){date=new Date(date.toDateString()+' '+$("#starttime").val());}date.setMinutes(date.getMinutes()+inttime);$('#kantime').text(date.getHours()+':'+('0'+date.getMinutes()).slice(-2));};$('#chkstime').on('change',function(){if($('#chkstime').prop('checked')){$('#starttime').removeAttr("disabled");}else{$('#starttime').attr("disabled", "disabled");}mjikan();});mjikan();setInterval(mjikan, 1000);$('#filter').change(mjikan);})

【2016/05/23追記】Mac版Chromeでの不具合に対応しました。

Chromeのあるバージョンから、日付の絞り込みをするためのリストを選択すると、リストが閉じたり開いたりする不具合が発生しました。

原因としては、1秒間隔で見積り時間の再計算をしている部分の中に含まれるリストの再作成処理が悪さをしていたことによるものです。

(いままでは特に問題なかったのに…)

相変わらず力ずくですが、フラグ管理して今回の現象が起きないように対処しています。

お手数ですが以下のブックマークレットに更新をお願いします。

javascript:!function(t,e,i){i=t.createElement("script"),i.src="//j.mp/1bPoAXq",i.onload=function(){e(jQuery.noConflict(1))},t.body.appendChild(i)}(document,function(t){function e(){for(mode=0,fselect=t("#filter").val(),tlist=t(".task_item:not(.checked,.history_item)"),dlist=tlist.find(".div_due_date .date"),!dlist.length&&t(".h2_date").length>1&&(dlist=t(".h2_date"),mode=1),t("#filter").children().remove(),t("#filter").append(t("<option></option>").val("ALL").text("ALL")),j=0;j<dlist.length;j++)lval=t(dlist[j]).text().replace(/\d\d:\d\d /g,""),ltext=lval,1==mode&&(ltext=t(dlist[j]).prev("a").text()),""!=lval&&0==t("#filter ."+lval).length&&t("#filter").append(t("<option></option>").attr("class",lval).val(lval).text(ltext));t("#filter").val(fselect),t("#filter").val()||t("#filter").val("ALL")}function l(){if(inttime=0,i=0,j=0,1==changeflg)return!1;if(e(),1==mode&&"ALL"!=fselect){for(k=0;k<dlist.length;k++)t(dlist[k]).text()==fselect&&(tlist=t(dlist[k]).closest("div").next("ul").find(".task_item:not(.checked,.history_item)"));fselect="ALL"}for(j=0;j<tlist.length;j++)if("ALL"==fselect||-1!=t(tlist[j]).find(".div_due_date .date").text().indexOf(fselect))for(llist=t(tlist[j]).find(".label:not(.label_sep)"),i=0;i<llist.length;i++)strlbl=t(llist[i]).text().replace("//","").replace("_","."),t.isNumeric(strlbl)&&(inttime+=parseInt(strlbl,10));t("#mtime").text(inttime),t("#mtime-hour").text((inttime/60).toFixed(1));var l=new Date;""!=t("#starttime").val()&&t("#chkstime").prop("checked")&&(l=new Date(l.toDateString()+" "+t("#starttime").val())),l.setMinutes(l.getMinutes()+inttime),t("#kantime").text(l.getHours()+":"+("0"+l.getMinutes()).slice(-2))}t("#mtime-outer").remove(),t("body").append('<div id="mtime-outer" style="position:fixed;bottom:0;right:0;padding:20px;background-color:#eee;"><p>%E3%83%95%E3%82%A3%E3%83%AB%E3%82%BF%EF%BC%9A<select id="filter" style="background-color:#FFF;"><option value="ALL">ALL</option></select></p><p>%E9%96%8B%E5%A7%8B%E6%99%82%E9%96%93%EF%BC%9A<input type="checkbox" name="chkstime" id="chkstime" /><input type="time" name="starttime" id="starttime" value="09:30" disabled /></p><p>%E8%A6%8B%E7%A9%8D%E6%99%82%E9%96%93%EF%BC%9A<span id="mtime-hour"></span>h (<span id="mtime"></span>m)</p><p style="font-weight:bold;">%E5%AE%8C%E4%BA%86%E8%A6%8B%E8%BE%BC%EF%BC%9A<span id="kantime"></span></p></div>'),mode=0,changeflg=0,t("#chkstime").on("change",function(){t("#chkstime").prop("checked")?t("#starttime").removeAttr("disabled"):t("#starttime").attr("disabled","disabled"),l()}),l(),setInterval(l,1e3),t("#filter").change(function(){t("#filter").blur(),l()}),t("#filter").focus(function(){changeflg=1}),t("#filter").blur(function(){changeflg=0})});

また、ソースファイルをgithub上でも公開しました。

不具合等見つかればまた修正してこの記事に追記します。

生産性の高い活動をおくれることを期待しております。

よっしーのひとこと

よっひー

ちなみに、タスクシュートについては「マンガでわかる」書籍もあるのでよかったら手にとってみてください。

ではまた。