original clock
HEXclock
Internet Time
Internet Time改
本日の経過ミリ秒

続・16進時計普及推進委員会

-internet Timeを作る-

いつもプログラミング言語の本を1冊買うとプログラムを1つ作っただけで納得してあとは忘れてしまう私ですが、JavaScriptは覚えるとなかなか使えるのではないかと思い、勉強を続けてみます。

高校時代はBASICのプログラムを作るとレポート用紙に書き出して人に渡すという、きわめて原始的な方法で配布したものです。(コピーさえしなかった。)
そのうちカセットテープに保存して渡すようになり、やがて5インチフロッピーの時代が来たのですが、私は使い物になるパソコンは3年前まで持っていなかったので、レポート用紙にアイデアを書いていって、大量のおやつと一緒に友人宅へ持っていって動作を確認するというスタイルは長く変わりませんでした。

様々なプログラミング言語やマシンがあった中で、このJavaScriptによるプログラミングは配布方法の軽さという点では画期的な気がします。
Javaアプレットならもっとすごいことができるのは知っていますが、Scriptではプログラムのソースそのものが簡単に見えるので、プログラミングの不細工な点やプログラムの制作態度まで伝わってしまいます。その点、レポート用紙に書きなぐって手渡すのに似ています。
何より自分のプログラムが人のマシンで特に断りなくスイスイ動いているというのは今までの経験に照らすと非常に刺激的なことでした。
それが仕事な人たちにはあまり何ともないことかも知れませんが。

さて、ノーガキが長くなりました。
今日はスクリプトの勉強第2限目(JavaScript歴6時間になりました)、Internet Time時計を自作して、HEXclockと比べてみよう(そしてHEXclockの長所を知ってもらおう)という演習です。
このページ左上に5つ窓があって、上から普通の時計、HEXtime、Internet Time、杉山風拡張Internet Time、0時からの経過時間、が表示されています。

スクリプトそのものはもう動いているのでソースをみていただければお話は終わりですが、主要部分を抜き出してみればこうなっています。

<SCRIPT LANGUAGE="JavaScript"> subsec=0; s=0; function multitime(){ setTimeout("multitime()",100); newtime=new Date(); ns=newtime.getSeconds(); if (s==ns){ subsec=subsec+1; } else{ subsec=0; } var orgtime=new Date(); h=orgtime.getHours(); m=orgtime.getMinutes(); s=orgtime.getSeconds(); //var totalsec=h*3600+m*60+s+subsec*0.1; var totalsec=((Date.parse(new Date)+32400000)%86400000)/1000+subsec*0.1 var totalswt=(totalsec+57600)%86400; var hexclock=Math.floor(totalsec/86400*65536); h=(h+100).toString().substring(1,3); m=(m+100).toString().substring(1,3); s=(s+100).toString().substring(1,3); hexclock=("000"+(hexclock.toString(16)).toUpperCase()); hexclock=hexclock.substring(hexclock.length-4,hexclock.length); var web=Math.floor(totalswt/86400*1000); subweb=(totalswt/86400*100000-web*100); neweb=(web+1000).toString().substring(1,4); neweb=neweb+"."+(subweb+100).toString().substring(1,3); document.clocks.original.value=(h+":"+m+":"+s); document.clocks.hexa.value=hexclock; document.clocks.webtime.value=("@"+web); document.clocks.newwebtime.value=("@"+neweb); document.clocks.PARSES.value=totalsec } </SCRIPT>

何ともすさまじいプログラムです。
N-BASICで作ったら0.1秒で処理が終わったかどうか怪しいものです。

まず取り組んだのは1日の経過秒数をGMT(グリニッジ標準時)に変換して、86400で割って1000を掛けることです。
たちまちそれらしい時計が動き始めました。
動作確認のため http://swatch.com/ からダウンロードして来たデスクトップ時計を並べてみたら、表示されている時間が違います。あれ?

改めてswatch.comを訪問して、普通時間<-->Internet Timeコンバータをいろいろと試しているうちにロンドンの午前0時が@000でないことに気がつきました。swatch社の所在地のスイス時間がInternet Timeの標準のようです。なんという愛国心。
日本と14時間の時間差をとるときちんと動作するようになりました。swatchの提供するデスクトップ時計は秒までしかチェックしていないようなので私のInternet Time時計の方がいくらか精密なようです。(正確というのとは別です)

次に物足りなくなったのは空き桁にゼロを追加する処理です。@1と表示するのが正しいのか@001と表示するのが正しいのかは知らないのですが、@001の方がかっこいいと思います。またHEXclockの方も午前零時を過ぎると「 A」なんて表示になって寂しいのでアセンブラのアドレス風に「000A」と表示させるよう改造します。
小数点以下2桁を取り出す場合は0.01の場合と0.10などの場合、単純に数字だけ取り出してしまってはどちらも1が取り出されてしまうため、いろんな場合を考えながら誤動作のないように調整していきます。考えた結果はかなり大胆な処理をしていますが。

最後に、ここまでは元となる時間をローカルタイムを時分秒に分解することによって取り出していましたが、JavaScriptのオブジェクトの中には1970年1月1日午前0時からの経過ミリ秒を取得するものがあるのでそれを利用する方法を考えてみました。経過ミリ秒と称している割には最後の3桁が必ず000なのでちょっと卑怯なオブジェクトですが。これはGMTが得られるらしく、処理にけっこう手間取りました。最初の方法による部分はコメントアウトして残してあります。(むしろ、最初の処理の方がスマートです。)
こうして一応動くようになったものがこのページに貼りつけてあるものです。

プログラムのソースは時としてプログラマーの人となりまで表してしまうものですが、私のプログラムは案の定雑然としています。行を変えて整然とやるべきことをごちゃ混ぜに一気にやってしまっています。それはスタイルの問題でまだよいのですが、自分でも許し難い問題を2つほど含んでいます。

1つは変数の取り扱い方で

hexclock=("000"+(hexclock.toString(16)).toUpperCase()); の行でそこまで数値変数として取り扱ってきたhexclockが、この行から文字変数になっているようなところです。こういう場合は別の変数名をとるべきでしょう。
BASICでは文字変数には「$」が付いているのでこういう間違いはしたくてもできないところです。
今回は、こんなこともできるのかと半ばふざけてやっています。夜も更けて新しい変数名を思いつくのがしんどかったのでそのままになっています。

もう1つの間違いは

ns=newtime.getSeconds(); if (s==ns){ subsec=subsec+1; } else{ subsec=0; }

のところで、さっきの回の時の秒と、新しく取得した秒を比較して、食い違ったら0.1秒の桁をリセットしているわけですが、よく考えるとたとえば秒の桁が1の時、sには文字列01が入り、nsには1が入っているはずです。これを比較したとき00〜09秒の10秒間は常に秒の桁が食い違って0.1秒の桁は一切進まないはずです。このプログラムはなぜ無事に動いているのでしょう?
(ブラウザによって動かないというレポートがありましたらぜひお寄せください)

さて、本題です。
swatchの推奨するInternet Timeと、当委員会の提唱するHEXtimeと、どちらが実用的でしょう。
実用性はswatchの方が勝るものの、見ていて楽しいのはHEXtimeの方だと思うのです!



お勉強が楽しくてこんな時間になってしまいました。

「なべのさかやき」目次に戻る