世界時計をサマータイム対応させてみた

世界時計をサマータイム対応させてみたのメイン画像

とある案件で、サマータイム実施地域のリアルタイムな時計を表示する必要が浮上! もともとの世界時計をカスタマイズして簡単に対応してみました。

01世界のサマータイムを調べる

サマータイムの仕組みって?

前回、簡易的な世界時計を作りましたが、実はそれだけでは不十分です。日本では馴染みがないですが、世界にはサマータイムを導入している国があるのです。
サマータイムとは、太陽が出ている時間帯を友好的に利用するために時間を進める制度です。夏時間の間、時間を30分~1時間早めることが多く、国によって開始日や時間が違います。

世界各国のサマータイム

世界のサマータイム実施状況をざっくりと調べてみました。

アメリカ・カナダ 3月第2日曜日 午前2時(夏時間午前3時) ~ 11月第1日曜日 午前2時(夏時間午前3時) -1時間
イスラエル 3月最終日曜日直前の金曜日 午前2時(夏時間午前3時) ~ 10月最終日曜 午前2時(夏時間午前3時) -1時間
ヨーロッパ 3月の最終日曜 午前2時(夏時間午前3時)~ 10月最終日曜 午前2時(夏時間午前3時) -1時間
オーストラリア 10月第1日曜日 午前2時(夏時間午前3時) ~ 翌年4月第1日曜日 午前2時(夏時間午前3時) -1時間

ほぼほぼ日曜日に夏時間の切り替えを行っているのかと思いきや、まれにイスラエルのような例外もあるようです。とはいえ、ルールさえ分かれば、サマータイムに対応できるはず…!?

02サマータイム開始・終了日時を表示する

まずはその年のサマータイム開始・終了日時を調べなければなりません。上記のパターンを見ると、第n週の日曜日か、最終日曜日の日付を取得できればどうにかできそうです。

第n週の日曜日の日付を取得する

試しに、2019年3月の第2日曜日の日付を取得したいと思います。そのためには、2019年3月1日の曜日を取得します。
var year = 2019,
    month = 3,
    first = new Date(year, (month - 1)),
    firstDay = first.getDay();
console.log(firstDay);

3行目のnew Date()メソッドに年と月の引数を渡すと、その月の1日の日時が返ります。
4行目のgetDay()メソッドは、日時データから曜日を取り出します。曜日は0~6の数字で返り、0が日曜、6は土曜にあたります。

ということは、2019年の3月1日は、金曜日だということですね!

var sun;
if(firstDay == 0){
    sun = 1;
}else{
    sun = 8 - firstDay;
}
sun += (n - 1)*7;
console.log('第' + n + '週の日曜日は' + sun + '日です');

月の最初の日曜日の日付を求めるために、まずは日曜日と金曜日の差分を出します。差分は7 - 5 = 2ですね!1日に差分の2を足すと3日になります。これをjavascriptで求めるなら1 + 7 - 5(firstDay)、つまり8 - firstDay(5行目)となるわけです。以上で月の最初の日曜日を求められました。最後に7行目で第n週の日曜日の日付を求めています。

最終日曜日の日付を取得する

第n週の日曜日はわかりましたが、最終日曜日の日付を出すにはやり方を変える必要があります。最終日曜日が第何週にあたるのか、分かりませんからね。ということでここでは例として10月の最終日曜日を求めてみます。

var year = 2019,
    month = 10,
    day = ['日','月','火','水','木','金','土'],
    last = new Date(year, month, 0),
    lastDate = last.getDate(),
    lastDay = last.getDay();
console.log(year + '年' + month + '月の末日は' + lastDate + '日' + dayk[lastDay] + '曜日です');

new Date()の第3引数に0を渡すと、渡した月の末日が返ります。

sun = lastDate - lastDay;
console.log(year + '年' + month + '月の最終日曜日は' + sun + '日です');

まずは末尾の曜日番号と日曜日の曜日番号の差分を求めます。日曜日 = 0なので、差分はそのまま末尾の曜日番号になります。1行目で末日から差分を引いた日付が最終日曜日の日付になります。

03サマータイム対応の時計を作る

ニューヨークの時計を作る

サマータイムの開始と終了日時が取得できれば、時計の表示も可能です!

// タイムゾーンを設定する
Date.prototype.setTimezone = function(tz){
    var utc = new Date(this.getTime() + this.getTimezoneOffset() * 60 * 1000);
    return new Date(utc.getTime() + tz / 100 * 60 * 60 * 1000);
};
var startMonth = 3, // サマータイム開始月
    startWeek = 2, // サマータイム開始週
    startTime = '02:00', // サマータイム開始時間(通常時間)
    endMonth = 11, // サマータイム終了月
    endWeek = 1, // サマータイム終了週
    endTime = '02:00', // サマータイム終了時間(通常時間)
    Tz = '-0500', // 通常のタイムゾーン
    summerTz = '-0400'; // サマータイム中のタイムゾーン,
	
// 第n週の日曜日を取得する関数
function getTheDay(year, month, num){
    var first = new Date(year, (month - 1)),
        firstDay = first.getDay(),
        sun;
if(firstDay == 0){
    sun = 1;
}else{
    sun = 8 - firstDay;
}
sun += (num - 1)* 7;
return sun;
}
// 時計表示の関数
function setTime(time){
    var h = ('0' + time.getHours()).slice(-2),
        m = ('0' + time.getMinutes()).slice(-2),
        s = ('0' + time.getSeconds()).slice(-2);
    msg = h + ':' + m + ':' + s;
    return msg;
}
setInterval(function(){
    var start,
        end,
        now = new Date(),
        dst = now.setTimezone(Tz),
        year = dst.getFullYear();
    // サマータイム開始日
    start = getTheDay(year, startMonth, startWeek);
    start = new Date(year+'/'+startMonth+'/'+start+' '+startTime).getTime();

    // サマータイム終了日
    end = getTheDay(year, endMonth, endWeek);
    end = new Date(year+'/'+endMonth+'/'+end+' '+endTime).getTime();

    // 現在がサマータイム中かどうかを判定して時間を取得
    var dstTime = dst.getTime();
    if(dstTime >= start && dstTime < end){
        // サマータイム
        var time = now.setTimezone(summerTz),
            msg = setTime(time);
    }else{
        // 通常時間
        var time = dst,
            msg = setTime(time);
    }
    $('時計を表示する要素').text(msg);
},1000);

6行目~13行目でNYのタイムゾーンやサマータイムの開始・終了に関する変数を指定しています。

NYの時計を表示させる処理は37行目から。44行目~45行目でサマータイムの開始日時を取得し、48行目~49行目で終了日時を取得します。なお、それらはあらかじめミリ秒単位の経過時間に直しています。

52行目で、タイムゾーンの現在時刻をミリ秒単位の経過時間になおし、数値化することで、53行目で現在時刻がサマータイムかどうかをif文で判定できるようにしています。現在時刻がサマータイム内であれば、ローカルタイムをサマータイム中のタイムゾーンにセットしなおし、時計を出力します。

これでニューヨークのサマータイム対応時計ができました!次回は、さらに汎用的なサマータイム対応時計を作ってみます!

この記事が役に立ったらシェアしてください!

  1. 世界のサマータイムを調べる
  2. サマータイム開始・終了日時を表示する
  3. サマータイム対応の時計を作る