日本では「サマータイム」として呼ばれることの多いですが、英語では どちらかというとDaylight Saving Time(DST)と書かれることが多いようです。 夏の期間、時計を1時間進めて昼間の時間を長くします。
世界約70ヶ国で実施されていて、その地域にはアメリカ、ヨーロッパ諸国に 加えてオーストラリア、ニュージーランド、 ブラジル、チリ、モンゴル、エジプト、リビア、イラク、イラン、トルコなど が含まれます。しかし、サマータイムの実施期間は国によってバラバラです。
今回対応したのはアメリカのサマータイムは1986年から実施されている方式で、 4月の最初の日曜日の午前2:00からサマータイムを開始し、時計を1時間進めます。 そして、10月の最終日曜日の午前2:00にサマータイムを終了し、時計を1時間 戻します。
たとえば、1999年のサマータイムは、1996年4月4日(日)に始まり、1999年10月31日(日)に 終わります。
蛇足ですが、アメリカでサマータイムが実施されているといっても、アメリカ 全体が対象地域なわけではなく、ハワイやアラスカは対象外です。また、 インディアナ州はサマータイムを実施していません。さらに見ていくと、 インディアナ州全部がサマータイムを実施していないわけではなく、隣の州と 隣接するカウンティの一部はサマータイムを実施していたりします。 面白いですねぇ。
1999年4月4日のGMT-5の時刻 | 1:55 | 1:56 | 1:57 | 1:58 | 1:59 | 2:00 | 2:01 | 2:02 |
1999年4月4日のニューヨークの現地時刻 | 1:55 | 1:56 | 1:57 | 1:58 | 1:59 | 3:00 | 3:01 | 3:02 |
1999年10月31日のGMT-5の時刻 | 0:55 | 0:56 | 0:57 | 0:58 | 0:59 | 1:00 | 1:01 | 1:02 |
1999年10月31日のニューヨークの現地時刻 | 1:55 | 1:56 | 1:57 | 1:58 | 1:59 | 1:00 | 1:01 | 1:02 |
上の表は、サマータイムの切り替え日の時刻がどのように変っていくのかを 示したものです。サマータイム開始日には、2:00になった瞬間に時計を1時間 進め3時にします。そういうわけで2:00台は存在しません。そして、サマータイム が終わる日には、サマータイムを実施している時計が2:00になった時に 1時間時計を戻します。なので、1:00台が2回繰り返されます。
タイムゾーンから割り出した時刻は表の1段目の時刻ですから、その時間で 開始終了時刻を表すと、サマータイム開始は、2:00からで、終了は1:00と いうことになります。
ここまででわかったことをJavaScriptで実現すると以下のようになります。
まず、サマータイム開始日、終了日の計算に用いる年(今日は何年か)を取得し、 変数yearに取っておきます。
次にサマータイム開始日を取得します。この機能はまとまりがいいので、 関数GetDstStart()として切り出します。 サマータイム開始日は、4月の第1日曜日なので、4月1日から7日までの間になるはずです(8日以降なら1度は日曜日になっているはず)。 4月1日2:00に対応するDateオブジェクトを作り、それからsetDate(i)で日付だけを 変更し、4月2日2:00、4月3日2:00、4月4日2:00…としていきます。ここで、 その曜日をgetDay()を使って取得し、それが日曜日(0 ゼロ)の場合はループを 打ち切ります。そうすると、dst_startは4月第1日曜日2:00amを表す時刻が 入っていますから、getTime()で内部表現の数値に変換して返します。today = new Date(); year = today.getYear(); if (year < 100) { year += 1900; }
結果は変数pos_startに取っておきます。
同様にサマータイム終了日時を取得する関数を作っておき、それを 呼び出します。今度は10月の最終日曜日を調べなければなりません。 10月31日から1日ずつ減らしながら、日曜日かどうかを確認し、 その日の1:00の内部表現を返します。 この関数を呼び出して、結果をpos_endに入れておきます。pos_start = GetDstStart(year); // 呼び出す方 // サマータイム開始日時の内部表現を取得する関数 function GetDstStart(arg_year) { var dst_start = new Date(arg_year, 3, 1, 2, 0, 0); // 第2引数の3は、4月を表す。 for (var i = 1; i <= 7; i++) { dst_start.setDate(i); if (0 == dst_start.getDay()) { break; } } return dst_start.getTime(); }
ここまでで準備はOKです。サマータイムの処理を行うのは、次の条件が 成り立つときです。pos_end = GetDstEnd(year); // 引数arg_yearで指定された年のサマータイム終了時刻を内部表現で返す。 // function GetDstEnd(arg_year) { 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()) { break; } } return dst_end.getTime(); }
以上の3点の条件が満たされたときに、現地の時刻に1時間足せば、サマータイム に対応できるというわけです。
function nowat(now_t, tz, st) { var hour, min, sec; var pos_t = now_t + (tz_offset + tz) * 60 * 1000; if (0 != st) { // サマータイム処理 if ((pos_start <= pos_t) && (pos_end > pos_t)) { pos_t += 60 * 60 * 1000; } } var t = new Date(); t.setTime(pos_t); hour = t.getHours(); min = t.getMinutes(); sec = t.getSeconds(); if (hour < 10) { hour = "0" + hour; } if (min < 10) { min = "0" + min; } if (sec < 10) { sec = "0" + sec; } return hour + ":" + min + ":" + sec; }
毎秒ごとに時計表示を書き換えるときには前の世界時計と同様に nowat()を呼び出します。サマータイム処理が必要のない東京のような場合は 第3引数に0を指定し、サマータイムが必要な都市の場合は第3引数に1を指定します。
function update_watch() { now = new Date(); n_t = now.getTime(); jp = nowat(n_t, tz_jp, 0); ny = nowat(n_t, tz_ny, 1); document.forms[0].elements[0].value = jp; document.forms[0].elements[1].value = ny; setTimeout('update_watch()', 999); // 1000msec = 1sec }
<FORM METHOD="post"> <BLOCKQUOTE> <TABLE> <TR><TD>東京<TD><INPUT NAME="tokyo" SIZE=8> <TR><TD>ニューヨーク<TD><INPUT NAME="newyork" SIZE=8> </TABLE> </BLOCKQUOTE> </FORM> <SCRIPT LANGUAGE="JavaScript"> // 引数arg_yearで指定された年のサマータイム開始時刻を内部表現で返す。 // function GetDstStart(arg_year) { var dst_start = new Date(arg_year, 3, 1, 2, 0, 0); // 第2引数の3は、4月を表す。 for (var i = 1; i <= 7; i++) { dst_start.setDate(i); if (0 == dst_start.getDay()) { break; } } return dst_start.getTime(); } // 引数arg_yearで指定された年のサマータイム終了時刻を内部表現で返す。 // function GetDstEnd(arg_year) { 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()) { break; } } return dst_end.getTime(); } // まず今が何年か調べます。 today = new Date(); year = today.getYear(); if (year < 100) { year += 1900; } // ここまでで、yearに今年の年(1998など)が入っています。 var tz_offset = today.getTimezoneOffset(); pos_start = GetDstStart(year); pos_end = GetDstEnd(year); tz_jp = 9 * 60; // GMT+9 tz_ny = -5 * 60; // GMT-0500 function nowat(now_t, tz, st) { var hour, min, sec; var pos_t = now_t + (tz_offset + tz) * 60 * 1000; if (0 != st) { // サマータイム処理 if ((pos_start <= pos_t) && (pos_end > pos_t)) { pos_t += 60 * 60 * 1000; } } var t = new Date(); t.setTime(pos_t); hour = t.getHours(); min = t.getMinutes(); sec = t.getSeconds(); if (hour < 10) { hour = "0" + hour; } if (min < 10) { min = "0" + min; } if (sec < 10) { sec = "0" + sec; } return hour + ":" + min + ":" + sec; } function update_watch() { now = new Date(); n_t = now.getTime(); jp = nowat(n_t, tz_jp, 0); ny = nowat(n_t, tz_ny, 1); document.forms[0].elements[0].value = jp; document.forms[0].elements[1].value = ny; setTimeout('update_watch()', 999); // 1000msec = 1sec } update_watch(); </SCRIPT>