code up

スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

JavaScriptで世界時計(タイムゾーンの変換)

JavaScriptでtimezoneを切り替えて、世界時計を作ってみます。

なんでこんなことをしているかというと、Adding a Timepicker to jQuery UI DatepickerというjQuery UIのDatePickerにTimePickerを追加するというアドオンを試用中なのだが、timezoneがうまく動いてくれないので外側で何とかしようかな、と。

上記プラグインはほどほどにデフォルトで使用するとして、タイムゾーンの切替はJavaScriptのDate型を駆使してプラグインの外側で制御することにした。

そして、せっかくなので世界時計を作ってみた。

そもそもJavaScriptのDate型はUTCの時刻とローカル時刻(日本の場合はJST+0900)しか表現できないらしいので、擬似的にそのタイムゾーンに合わせたDate型を生成しているだけです。従ってtoString等でタイムゾーン付きで出力すると合ってないです。

つまり↓こんな感じ。

世界標準時

日本

ハワイ

スクリプト全体。

<script type="text/javascript">
String.prototype.right = function(n){
	return this.substr(this.length - n, n);
};

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);
};

$(function(){
  setInterval(function(){
    var now = new Date();
    $('.timezone').each(function(){
      var dst = now.setTimezone($(this).attr('data-timezone'));

      // UTC日時は合ってないのでtoTimeStringやgetUTCHoursは使えない。

      $(this).val(
        dst.getFullYear() + '/'
        + ("0" + (dst.getMonth() + 1)).right(2) + '/'
        + ("0" + dst.getDate()).right(2) + ' '
        + ("0" + dst.getHours()).right(2) + ':'
        + ("0" + dst.getMinutes()).right(2) + ':'
        + ("0" + dst.getSeconds()).right(2)
      ).next().text(dst);
    });
  }, 1000);

});</script>

続いてHTML部分。

<form>
<p><input type="text" class="timezone" data-timezone="+0000" /><label style="color: red;"></label> 世界標準時</p>
<p><input type="text" class="timezone" data-timezone="+0900" /><label style="color: red;"></label> 日本</p>
<p><input type="text" class="timezone" data-timezone="-1000" /><label style="color: red;"></label> ハワイ</p>
</form>

ポイントとなるタイムゾーン変換はDateクラスを拡張している。

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);
};

日本時間に合わせたPCが3つめのハワイ日時を出すまでを例に説明する。

まずthis.getTime()で1970/01/01 00:00:00 UTCからのミリ秒を取得する。これはタイムゾーン関係なくどこの国でも一緒。

続いてthis.getTimezoneOffset()でローカルPCの(今回の場合日本の)UTCとの差分を分で得る。日本の場合-540分(=9時間)が返ってくる。桁をミリ秒にそろえ(* 60 * 1000)、足し算(マイナス値なので正確には引き算)した引数で新しいDateオブジェクトを作成する。この時点で疑似UTC時間となっている(変数utc)。

疑似と言っているのは、正確にはこのオブジェクトはUTC時間から-540分した日時を表しているから。でも、関係ない。なぜなら今回のケース(最初に書いたjQuery UI用のアドオン)で最終的に日時を得るためのメソッド(上記例であればgetFullYear/getMonth/getDate/getHours/getMinutes/getSeconds)はそのDateオブジェクトをローカルのタイムゾーンで解釈して表示しているため。

もう少しかみ砕くと、現在時刻が日本時間で2013/02/20 16:00だったとして、その時点のUTC時間は9時間引いて2013/02/20 07:00である。このUTC時間を9時間戻したとする→ 2013/02/19 22:00。そうすると、その時点の日本時間は2013/02/20 07:00となる。この状態でgetHoursすると(Dateオブジェクト内のUTC日時を日本時間に変換して)7時を返してくる。この日本時間から-9時間した日本時間を疑似UTC日時と説明している。

上記疑似UTC日時に対して指定されたタイムゾーン(ハワイであれば-1000)で更に日時を移動させる。タイムゾーンの書式は[+|-]HHmmという書式であるが、単に100で割って時間にしミリ秒にかけ算しているので例えば+0545といったタイムゾーンは上記例ではうまく動作しませんm(_ _)m ※最下部に対応版を掲載。

上の例で、疑似UTC日時に対して同じ方法でハワイのタイムゾーンを足す(ハワイの場合実際は引く)。すると疑似ハワイ日時ができあがる。このオブジェクトに対してgetHoursなどでハワイの日時を取得することができる。

内部のUTC日時は日本時間から-9時間、さらに-10時間引いた値なので正確には最初の日時から-19時間した時間となっている。

最終的にjQueryに統合した形で完成したもの。'-05:45'の書式にも対応。

$.extend(Date.prototype, {
	/**
	 * tz: 例: '+09:00', '-05:45'
	 */
	setTimezone: function(tz){
	    var utc = new Date(this.getTime() + this.getTimezoneOffset() * 60 * 1000);
	    var tzm = +(tz.replace(/:/g, '')); // -0545 → -545
	    var mm = tzm % 100; // -45
	    var hh = tzm - mm;  // -500
	    return new Date(utc.getTime() + ((hh / 100 * 60) + mm) * 60 * 1000);
	}
});

結局上記アドオンは使用しないことにした。タッチパネル系の事を考え、結局時間選択はプルダウンで普通に作った。

関連記事
タグ:JavaScript
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。