JavaScript で世界時計を作ってみました。ロンドン、東京、ロサンゼルス、ニューヨークの時刻を表示するサマータイム対応のプログラムです。
この世界時計は JavaScript の作られており、表示するのはロンドン、東京、ロサンゼルス、ニューヨークの4都市。アメリカ、イギリスそれぞれのサマータイム(DST/Daylight Saving Time)にも対応しているほか、時刻に合わせて背景色が変わる、という機能もついています。
より詳しく書きますと、このプログラムは DOKUGAKU JavaScript というサイトが提供している、「世界時計(米国サマータイム対応)」というサンプルプログラムを拡張したもの、ということになります。
拡張したものは主に以下の 4 つです。
これらの拡張機能は、あると便利そうだなと個人的に思ったものを機能として実装しています。
まず 2. についてですが、イギリスとアメリカではサマータイム期間が微妙に違っており、プログラムにその違いを実装する必要がありました。サマータイム情報 というページによるとアメリカのサマータイムは「4月第1日曜日から10月最終土曜日まで」であるのに対し、イギリスのは「3月最終日曜日の午前2:00から10月最終日曜日の午前2:00」となっています。このプログラムではアメリカ版サマータイム用とは別にイギリス版のサマータイム用の関数を作成して対応しています。
3. についてですが、これは視覚的な効果を狙ってつけた機能です。実は上記に挙げた拡張機能リストのうち、1. と 2. に関しては 2001 年 10 月の時点で完成していてその状態でずっと使ってきたのですが、時刻を数値でただ表示だけではつまらないなという思いがありました。例えば、プログラムが「LDN 01:30 TYO 09:30 LAX 17:30 NYC 20:30」と表示していたとします。これを見ればロンドン、ニューヨークが夜でロサンゼルスは夕方、というのはすぐわかるのですが、でも各都市の時刻を情報として認識するのと、各都市の空がどのようになっているのか(朝方で明るいのか深夜で暗いのか、など)をイメージするのは全く別のことであるように思います。もちろん自分の頭の中で考えれば各都市の空の明るさは簡単にイメージできるのですが、その行為をプログラムの視覚的機能で支援すれば、イメージはより簡単になり便利になるのではないかと考えました。そのような経緯から、この時間に合わせて背景色を変えるという機能をつけることにしました。
箇条書きのカッコ内にあるとおり、日中を白として夜中に近づくにつれて青くなるよう設定しています。当初、この機能は JavaScript 単独で実装可能だろうと考えていたのですが、どうやらそう話は簡単ではないようで、最終的には JavaScript と CSS を組み合わせて使うことで実装するに至っています。ちなみに背景色は全部で 4 色用意されており、時刻との対応は以下のようになっています。
この機能により、地球上のどこに太陽の光が当たっていて、どこが当たっていないのか、という想像もできるようになり、その意味でもこの機能は有用でおもしろい機能なのではないかと思います。
また、「LDN」「TYO」などの見慣れない書き方が気になるかもしれませんが、これは航空業界で日常的に使われている「スリーレター」というもので、世界の全空港を英文字 3 文字で区別するための仕組みです。このプログラムではスリーレターの形式をとりつつ、多少特殊なやりかたで表記しています(たしか NYC というスリーレターはなかったように思います)。
4. の「インターネットタイム」についてですが、これはスイスの SWATCH 社が提唱する全く新しい時間フォーマットで一日24時間を 1000 に分け、それを「ビート」という単位であらわすものです(表記は「@276」のようになります)。この時間フォーマットには時差がないので、海外の人とチャットや電話の約束をするときにいちいち時差を計算する必要がなくなります。「@276に電話するね」と言ったら、それがニューヨークでもロンドンでも同一時刻を表していることになるのです。詳細は Apple が用意しているページ をご参照ください。
あえて難を挙げるとすれば、時差の問題は解決できるにしても日付変更線の問題を解決することはできないということでしょうか。例えば、方やロサンゼルス、方や東京に住む友達同士が「今度の土曜日の @775 にチャットしようね」と約束したとします。東京の人にしてみればこれは「今度の土曜の午前 2 時 37 分にチャットをする」ということになり、ロサンゼルスの人にしてみれば「今度の土曜の午前 10 時 37 分にチャットをする」ということになります。チャットをする以上、当然ながら 2 人はまったく同じ時間に PC の前で準備をしなければならないですが、このケースでは、2 人はチャットをすることはできません。なぜなら 2 人の「土曜日」には時差があるからです。東京の人にとっての「土曜日の @775」、つまり「土曜日午前 2 時 37 分」は、ロサンゼルス時間でいう「金曜日午前 10 時 37 分」であり、ロサンゼルスの人とっての「土曜日の @775」、つまり「土曜日午前 10 時 37 分」は東京時間でいう「日曜日午前 2 時 37 分」となります。2人の間には常に24時間分の時差が発生してしまい、2人はこの問題に気づかない限り、永久にチャットすることはできません。
話が脇道にそれてしまいましたが、日付変更線の問題はあるにせよ、時差の概念をなくすという意味でインターネットタイムには有用性があるように思います。今回のプログラムでは NI-Lab. というサイトのプログラムを参考にインターネット機能を実装しました。
CGI スクリプトやデスクトップアプリケーションとは異なり、JavaScript によるプログラムは、良くも悪くも仕組みを実装するソースコードがブラウザの「ソースを表示」というメニューを選ぶことで簡単に見られるようになっています。隠そうにも隠しようがない、それなら……ということでこのサイトには珍しくプログラムのソースコードをまるまる掲載したいと思います。何かの参考にしてください。
ちなみにこのプログラムを利用・参考にするときは僕のクレジットかこのサイトへのリンクを付けてくだされば幸いに思いますが、must ではございません。また、見よう見真似で作った習作レベルのプログラムなのでソースコードの「エレガントさ」にはほとんど自信がありません。ただ動きますよ、というレベルです。
JavaScript の外部ファイル「worldclock.js」のソースコードです。
/*
*
* ◆ worldclock.js
*
* CREATED: 2001-10-23
* MODIFIED: 2002-07-20
* BY Yuki SHIMAZU
*
* ◇参考資料
* http://www.ueda.info.waseda.ac.jp/~gaku/js/how034.html
* http://isweb13.infoseek.co.jp/computer/nilab/dl.html
* http://www.apple.co.jp/hotnews/swatch/index.html
* http://www.swatch.com/internettime/
* http://www.ne.jp/asahi/taka/hello/summer.html
* http://www.inside.ne.jp/js/
*
*/
// まず今が何年か調べる
var today = new Date();
var year = today.getYear();
if (year < 1900) { year += 1900; }
// ローカル時間とグリニッジ標準時の差を分で表示
var tz_offset = today.getTimezoneOffset();
// 米英のサマータイムの期間を格納
var pos_startUS = GetDstStartUS(year);
var pos_endUS = GetDstEndUS(year);
var pos_startUK = GetDstStartUK(year);
var pos_endUK = GetDstEndUK(year);
// 各都市の時差を格納
var tz_ldn = 0 * 60; // GMT +-0
var tz_tyo = 9 * 60; // GMT +9
var tz_lax = -8 * 60; // GMT -8
var tz_nyc = -5 * 60; // GMT -5
//
// ◆各都市の表示欄の色づけ
//
cities = Array(4);
cities[0] = "ldn";
cities[1] = "tyo";
cities[2] = "lax";
cities[3] = "nyc";
document.writeln("<style type=text/css>");
// いまの時刻を取得(たぶん1000ミリ秒単位)
var now = new Date();
var n_t = now.getTime();
for ( i=0; i<4; i++ ) {
if (cities[i] == "ldn") { var str = printtime(n_t,tz_ldn); }
else if (cities[i] == "tyo") { var str = printtime(n_t,tz_tyo); }
else if (cities[i] == "lax") { var str = printtime(n_t,tz_lax); }
else if (cities[i] == "nyc") { var str = printtime(n_t,tz_nyc); }
var hour = str.substring(0,2);
/*
* ○時刻ごとの背景色設定
* 白 ....... 6-16
* 薄い青 ... 16-18, 5-6
* 青 ....... 18-20, 4-5
* 濃い青 ... 20-4
*/
if ( 6 <= hour && hour < 16 ) {
document.writeln("input." + cities[i] + " { background:#eee }");
} else if ( (16 <= hour && hour < 18) || (5 <= hour && hour < 6) ) {
document.writeln("input." + cities[i] + " { background:#ccf }");
} else if ( (18 <= hour && hour < 20) || (4 <= hour && hour < 5) ) {
document.writeln("input." + cities[i] + " { background:#77c;color:#ddd }");
} else {
document.writeln("input." + cities[i] + " { background:#448;color:#ddd }");
}
}
document.writeln("</style>");
// ◆メインルーチン
function update_watch() {
// いまの時刻を取得(たぶん1000ミリ秒単位)
var now = new Date();
var n_t = now.getTime();
document.worldclock.ldn.value = printtime(n_t,tz_ldn);
document.worldclock.tyo.value = printtime(n_t,tz_tyo);
document.worldclock.lax.value = printtime(n_t,tz_lax);
document.worldclock.nyc.value = printtime(n_t,tz_nyc);
document.worldclock.internettime.value = internettime();
setTimeout('update_watch()', 999); // 1000msec = 1sec(秒)
}
// ◆米国版 DST 開始設定(4月第1日曜日2:00AM から 10月最終日曜日1:00AM まで)
// 引数arg_yearで指定された年のサマータイム開始時刻を return で返す
function GetDstStartUS(arg_year) {
// 第2引数の3→4月 第3引数の1→1日 第4引数の2→2:00AM
var dst_start = new Date(arg_year, 3, 1, 2, 0, 0);
for (var i = 1; i <= 7; i++) {
dst_start.setDate(i);
if (0 == dst_start.getDay()) { // 0は日曜日を意味する
break;
}
}
return dst_start.getTime();
}
// ◆米国版 DST 終了設定(4月第1日曜日2:00AM から 10月最終日曜日1:00AM まで)
// 引数arg_yearで指定された年のサマータイム終了時刻を return で返す
function GetDstEndUS(arg_year) {
// 第2引数の9→10月 第3引数の31→31日 第4引数の1→1:00AM
var dst_end = new Date(arg_year, 9, 31, 1, 0, 0);
for (var i = 31; i > 24; i--) {
dst_end.setDate(i);
if (0 == dst_end.getDay()) { // 0は日曜日を意味する
break;
}
}
return dst_end.getTime();
}
// ◆英国版 DST 開始設定(3月最終土曜日2:00AM から 10月最終土曜日2:00AM まで)
// 引数arg_yearで指定された年のサマータイム開始時刻を return で返す
function GetDstStartUK(arg_yearUK) {
// 第2引数の2→3月 第3引数の31→31日 第4引数の2→2:00AM
var dst_startUK = new Date(arg_yearUK, 2, 31, 2, 0, 0);
for (var i = 31; i > 24; i--) {
dst_startUK.setDate(i);
if (6 == dst_startUK.getDay()) { // 6は土曜日を意味する
break;
}
}
return dst_startUK.getTime();
}
// ◆英国版 DST 終了設定(3月最終土曜日2:00AM から 10月最終土曜日2:00AM まで)
// 引数arg_yearで指定された年のサマータイム終了時刻を return で返す
function GetDstEndUK(arg_yearUK) {
// 第2引数の9→10月 第3引数の31→31日 第4引数の2→2:00AM
var dst_endUK = new Date(arg_yearUK, 9, 31, 2, 0, 0);
for (var i = 31; i > 24; i--) {
dst_endUK.setDate(i);
if (6 == dst_endUK.getDay()) { // 6は土曜日を意味する
break;
}
}
return dst_endUK.getTime();
}
// ◆表示・サマータイム処理
function printtime(now_time, timezone) {
var hour, min, sec;
var pos_t = now_time + (tz_offset + timezone) * 60 * 1000;
// サマータイム処理
if (timezone == tz_ldn) {
// ロンドン編
if ((pos_startUK <= pos_t) && (pos_endUK > pos_t)) {
pos_t += 60 * 60 * 1000;
}
} else if ( timezone == tz_lax || timezone == tz_nyc ) {
// LA & NY 編
if ((pos_startUS <= pos_t) && (pos_endUS > pos_t)) {
pos_t += 60 * 60 * 1000;
}
}
var t = new Date();
t.setTime(pos_t);
hour = t.getHours();
min = t.getMinutes();
sec = t.getSeconds();
// 「XX時00分00秒」で、かつ、XX が「4,5,6,16,18,20」のうち
// いずれかであるときにページをリロード
// この処理により時間ごとの背景色が自動的に変わる
if ( (hour==4||hour==5||hour==6||hour==16||hour==18||hour==20) && min==0 && sec==0 ) {
window.location.reload();
}
if (hour < 10) {
hour = "0" + hour;
}
if (min < 10) {
min = "0" + min;
}
if (sec < 10) {
sec = "0" + sec;
}
return hour + ":" + min + ":" + sec;
// return hour + ":" + min;
}
// ◆インターネットタイムの処理
function internettime() {
var c = new Date();
var gmt = c.toGMTString();
var d = gmt.indexOf(":")
var h = eval( gmt.slice(d-2,d) );
var m = eval( gmt.slice(d+1,d+3) );
var s = eval( gmt.slice(d+4,d+6) );
// LONDON と BIEL(SWATCH本社所在地/PARISとtime zoneが同じ)の 時差は1時間(3600秒)
var beat = (h * 3600 + m * 60 + s + 3600) / 86.4;
if (beat >= 1000) beat = beat - 1000;
beat = Math.floor(beat);
var zero = "";
if (beat < 100) zero = "0";
if (beat < 10) zero = "00";
return "@" + zero + beat;
}
続いて、世界時計を表示するための HTML ファイルです。
<html>
<head>
<title>World Clock</title>
<meta http-equiv="content-Type" content="text/html; charset=Shift_JIS">
<script type="text/javascript" src="worldclock.js"></script>
<style type="text/css">
input.internettime {
background:#eee;
}
</style>
</head>
<body bgcolor="#ffffff" onLoad="update_watch()">
<h1>World Clock</h1>
<form method="post" name="worldclock">
<span style="font-size:smaller">LDN: </span><input name="ldn" class="ldn" size=8>
<span style="font-size:smaller">TYO: </span><input name="tyo" class="tyo" size=8>
<span style="font-size:smaller">LAX: </span><input name="lax" class="lax" size=8>
<span style="font-size:smaller">NYC: </span><input name="nyc" class="nyc" size=8>
<br><br>
<span style="font-size:smaller">INTERNET TIME: </span>
<input name="internettime" class="internettime" SIZE="5">
</form>
</body>
</html>