日本では「サマータイム」として呼ばれることの多いですが、英語では どちらかというと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に取っておきます。
today = new Date();
year = today.getYear();
if (year < 100) {
year += 1900;
}
次にサマータイム開始日を取得します。この機能はまとまりがいいので、
関数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()で内部表現の数値に変換して返します。
結果は変数pos_startに取っておきます。
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();
}
同様にサマータイム終了日時を取得する関数を作っておき、それを
呼び出します。今度は10月の最終日曜日を調べなければなりません。
10月31日から1日ずつ減らしながら、日曜日かどうかを確認し、
その日の1:00の内部表現を返します。
この関数を呼び出して、結果をpos_endに入れておきます。
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();
}
ここまでで準備はOKです。サマータイムの処理を行うのは、次の条件が
成り立つときです。
以上の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>