TECHNICAL INFORMATION技術情報

第6回
  タイマー、日付と時刻

タイマー

 ある時間後や、ある時間ごとに処理をするためには、タイマーを使います。

 変数 = setTimeout(実行する処理, 時間[ミリ秒])
 clearTimeout(変数)

 setTimeout はタイマーを設定し、ここで指定した変数を clearTimeout で指定することで、タイマーを解除します。

<!DOCTYPE HTML> <html> <head> <meta charset="utf-8"> <script> var tm,i=0; function msg() { mes=new Array("いらっしゃい","よくきたな","もう帰るの","バイバイ"); document.form01.txt01.value=mes[i]; i++; if(i==4) i=0; clearTimeout(tm); tm=setTimeout("msg()",1000); } </script> </head> <body> <form name="form01"> <input type="button" value="スタート" onclick="msg()">  <input type="button" value="ストップ" onclick="clearTimeout(tm)"><p> <input type="text" name="txt01"> </form> </body> </html>

 ここをクリックしてください。この例では [スタート] をクリックすると、setTimeout により、1000ミリ秒 = 1秒ごとに、メッセージを繰り返し表示し、[ストップ] をクリックするとこのタイマーを止めます。なお、msg() の中で、clearTimeout(tm) を実行していますが、これがないと、 [スタート] を複数回クリックしたときに、タイマーが複数起動してしまいます。

● 当選番号を決める例

 次の例は、タイマーと乱数を利用して、多くの番号の中から当選番号を決めるものです。ここをクリックしてください。最小/最大ナンバーを入力して、[スタート] をクリックすると、乱数により、50~150ミリ秒間隔に [当選ナンバー] の番号が変わり、[ストップ] をクリックすると、このとき [当選ナンバー] に表示されていた番号が [当選リスト] のコピーされます。
 なお、当選した番号は配列 nnum に代入して、 [当選ナンバー] に表示する前にチェックし、ダブリがないようにしています。最小~最大ナンバーが全て出てしまうと、[終了しました] というメッセージを出します。

<!DOCTYPE HTML> <html> <head> <meta charset="utf-8"> <script> var d01,d02; var tm; nnum=new Array(); function calc() { with(document.form01) { d01=txt01.value*1; // 最小ナンバー d02=txt02.value*1; // 最大ナンバー if(nnum.length==d02-d01+1) // 全てのナンバーが出たら終了 alert("終了しました"); else if(d02 > d01) { clearTimeout(tm); mcalc(); } else alert("正しい数値を入力してください"); } } function mcalc() { var i,ttemp,snum,flag=1; ttemp=(Math.floor(Math.random()*100))+50; // 50~100ミリ秒 tm=setTimeout("mcalc()",ttemp); with(document.form01) { while(flag==1) { // snum は最小~最大の間のランダムな整数 snum=Math.floor(Math.random()*(d02-d01+1))+d01; for(i=0;i<nnum.length;i++) { if(snum==nnum[i]) // すでに出たナンバーと同じなら中止 { flag=0; break; } } if(flag==1) { txt03.value=snum; // 数字を代入 flag=0; } else flag=1; } } } function mlist() { with(document.form01) { if(txt03.value!=nnum[nnum.length-1]) { clearTimeout(tm); nnum[nnum.length]=txt03.value; list.value=" No."+txt03.value+"\n"+list.value; } // [ストップ] を続けて押したときは処理しない } } </script> </head> <body> <form name="form01"> 最小ナンバー:<input type="text" name="txt01"><br> 最大ナンバー:<input type="text" name="txt02"><p> <input type="button" value="スタート" onclick="calc()">  <input type="button" value="ストップ" onclick="mlist()"><p> <hr>当選ナンバー:<input type="text" name="txt03"><p> <hr>当選リスト<br> <textarea name="list" rows="10" cols="20"></textarea> <input type="reset" value="リセット" onclick="nnum.length=0"> </form> </body> </html>

日付と時刻

 現在の日付と時刻を得るためには、new を使用して日付オブジェクトを作成します。ここをクリックしてください。[表示] をクリックすると、Aには、Date() で作成した、現在の日付/時刻の日付オブジェクト dtm が表示されます。Bには、日付オブジェクト dtm より得た値から、日本語表記の時刻の日付が表示されます。Cには toGMTString によりグリニッジ標準時、Dには toLocaleString によりローカル時が表示されます。

<!DOCTYPE HTML> <html> <head> <meta charset="utf-8"> <script> function disp() { week=new Array("日","月","火","水","木","金","土"); dtm=new Date(); var yy=dtm.getFullYear(); var mm=dtm.getMonth()+1; var dd=dtm.getDate(); var ww=week[dtm.getDay()]; var hh=dtm.getHours(); var nn=dtm.getMinutes(); var ss=dtm.getSeconds(); with(document.form01) { txt01.value=dtm; txt02.value=yy+"年"+mm+"月"+dd+"日("+ww+"曜日)"+hh+"時"+nn+"分"+ss+"秒"; txt03.value=dtm.toGMTString(); txt04.value=dtm.toLocaleString(); } } </script> </head> <body> <form name="form01"> a:<input type="text" name="txt01" size=50>(dtm)<br> b:<input type="text" name="txt02" size=50>(日本語表記)<br> c:<input type="text" name="txt03" size=50>(グリニッジ標準時)<br> d:<input type="text" name="txt04" size=50>(ローカル時)<p> <input type="button" value="表示" onclick="disp()"> </form> </body> </html>

 このなかで、getFullYear は古いブラウザが対応していません。対応している getYear の場合、2000年以降の表示がブラウザにより異なってしまうので、ここでは getFullYear を使用しています。getMonth は0から始まり、実際の月より1小さい値になるので、+1 しています。
 getMonth などを使用して表示するB以外は、ブラウザにより表示が異なります。

● 曜日と、今日から何日目かを表示する例

 入力した日の曜日と、今日から何日目かを表示します。ここをクリックしてください。

<!DOCTYPE HTML> <html> <head> <meta charset="utf-8"> <script> function disp() { week=new Array("日","月","火","水","木","金","土"); dtm=new Date(); with(document.form01) { var yy=txt01.value; var mm=txt02.value-1; var dd=txt03.value; dtn=new Date(yy,mm,dd); txt04.value=week[dtn.getDay()]; txt05.value=Math.ceil((dtn.getTime()-dtm.getTime())/8.64E07); } } </script> </head> <body> 年(4桁)、月、日 を入力してください。 <form name="form01"> <input type="text" name="txt01" size=5>年 <input type="text" name="txt02" size=3>月 <input type="text" name="txt03" size=3>日  <input type="button" value="表示" onclick="disp()">  <input type="reset" value="リセット"> <hr> この日は<input type="text" name="txt04" size=4>曜日  今日から<input type="text" name="txt05" size=10>日目です。 </form> </body> </html>

 Date() は、引数を省略すると、現在の日付と時刻の日付オブジェクトを作成しますが、日付を表す文字列を指定できます。この日の曜日を getDay で求めます。
 getTime は、日付オブジェクトから、1970年1月1日0時からの経過時間をミリ秒で返します。現在との差を、1日の時間をミリ秒で表した 8.64E07(60*60*24*1000) で除して日にしています。

● マウスをクリックする反応速度を測定する例

 表示が変わってから、マウスをクリックするまでの反応速度を測定するものです。ここをクリックしてください。[スタート] をクリックすると、2~3秒後にテキストボックスに黒い ■ が表示されます。表示されてからクリックするまでの時間を表示して、判定します。

<!DOCTYPE HTML> <html> <head> <meta charset="utf-8"> <script> var tm,t01; function calca() { var ttemp; ttemp=(Math.floor(Math.random()*1000))+2000; tm=setTimeout("calcb()",ttemp); t01=(new Date()).getTime()+ttemp; } function calcb() { document.form01.txt01.value="■■■■■■■■■■■"; clearTimeout(tm); } function calcc() { var t02; t02=(new Date()).getTime(); with(document.form01) { txt02.value=t02-t01; if((t02-t01)<=0) txt03.value="黒くなってからクリックしてください"; else if((t02-t01)<=200) txt03.value="速すぎ!!"; else if((t02-t01)<=400) txt03.value="普通です"; else txt03.value="ちょっと遅いんじゃ..."; } } </script> </head> <body> <form name="form01"> 反応速度テスト  <input type="button" value="スタート" onclick="calca()"><p>  <input type="text" name="txt01" size=20>  <input type="button" value="クリック" onclick="calcc()"><hr> 時間:<input type="text" name="txt02" size=20>ミリ秒<br> 判定:<input type="text" name="txt03" size=40>  <input type="reset" value="リセット"> </form> </body> </html>

 やってみると、速くクリックしたようでも、表示される時間はだいぶ大きくなります。プログラムとしては正しくても、ミリ秒まで正確に得ることはできないようで、反応速度を正確に測定するのは無理のようです。小さい数値を出すには、黒くなる前に予測してクリックする必要があるので、ゲーム的には使えるかもしれません。

● カレンダーの例

 ロードしたときは今月のカレンダーを表示し、[前月]/[次月] または、入力した年月のカレンダーを表示することができます。ここをクリックしてください。

<!DOCTYPE HTML> <html> <head> <meta charset="utf-8"> <script> function dispm() { var i; week=new Array("日","月","火","水","木","金","土"); dtm=new Date(); with(document.form01) { for(i=0;i<=6;i++) // 曜日を代入 elements[i+7].value=week[i]; txt01.value=dtm.getFullYear(); txt02.value=dtm.getMonth()+1; txt03.value=txt01.value+"年"+txt02.value+"月"+dtm.getDate()+"日" } disp(); } function dispn(tp) { with(document.form01) { if(tp.value=="前月") { if(txt02.value==1) // txt01:年 txt02:月 { txt02.value="12"; txt01.value--; } else txt02.value--; } else { if(txt02.value==12) { txt02.value="1"; txt01.value++; } else txt02.value++; } } disp(); } function disp() { var i,j,k,d01,d02; with(document.form01) { d01=txt01.value; //d01:年 d02:月 d02=txt02.value-1; if(d01<=0 || d02<0 ||d02>11) { alert("入力した値が異常です。本日に戻ります。"); dispm(); return false; } j=(new Date(d01,d02,1)).getDay(); // j はこの月の1日の曜日 if(d02==12) k=(new Date(d01+1,1,1)).getDay(); // k は次月1日の曜日 else k=(new Date(d01,d02+1,1)).getDay(); for(i=1;i<=42;i++) elements[i+13].value=""; // カレンダーを空白に初期化 for(i=1;i<=31;i++) { if(i>=28 && (new Date(d01,d02,i)).getDay()==k) break; // 曜日が次月1日と同じなら中止 elements[i+j+13].value=i; // 日を代入 } } } </script> </head> <body onload=dispm();> <form name="form01"> <input type="text" name=txt01 size=5>年 <input type="text" name=txt02 size=3>月  <input type="button" value="表示" onclick="disp()")> <p><input type="button" value="前月" onclick="dispn(this)")> <input type="button" value="次月" onclick="dispn(this)")>  <input type="button" value="本日" onclick="dispm()")> <input type="text" name=txt03 size=20><hr> <script> var tb; for(tb=1;tb<=49;tb++) { document.write("<input type='text' size=2>"); if(tb%7==0) document.write("<br>"); } </script> </form> </body> </html>

 ロードしたとき、[本日] をクリックしたとき、入力された年月が異常なときは、dispm() が実行されて、今月のカレンダーが表示されます。
 disp() がカレンダーに数字を表示する部分です。まず、年月に異常な数字が入力されている場合は、メッセージを出してから dispm() を実行して、本日に戻ります。この月の1日の曜日を j=(new Date(d01,d02,1)).getDay() により求め、入力するテキストボックスの位置を決めます。その月が何日まであるか? を知るために、28日以後の曜日を、次の月の1日の曜日と比較して、同じなら入力を終了しています。