時を超えた javascript の道
DESCRIPTION
at Shibuya.js beyond HTML5 (2010/07/30) http://atnd.org/events/6730TRANSCRIPT
時を超えた JavaScript の道
@teppeis
Shibuya.js beyond HTML5 2010/07/30
自己紹介
経緯
席が向かえの amachang と机の下で足があたったりして キャッキャウフフ ヾ(*´∀`*)ノ するリア充生活を送っていたら、いつのまにか LT することになっていました。お手柔らかにおねがいします!
さて、国際化が叫ばれる昨今
社内公用語の英語化が話題です。
ちょっと待って!
国際化といえば、タイムゾーンを忘れてませんか?
ということで、JavaScript のタイムゾーンの話をします。
とりあえずデモ
画面上の時刻表示を変換する Chrome 拡張ATND の microformats を読み取って、PST(太平洋標準時)に変換します。
音響カプラと3Dと
顔文字アセンブラのあとに
この地味なデモ。
Warningこっから
地味な話が続きます。眠たい人は
今がチャンスです。
Date Object in JavaScript
new Date() はローカルタイムを生成ローカルタイムとUTCのみを扱えるローカルタイムのタイムゾーンはOS設定夏時間の計算方法は環境依存
え。ということは?
UTCやOS設定以外のタイムゾーンを扱うことができない環境によって日時表示や日時計算がずれる場合がある
いろんなTZを扱いたいケース
例)JST を PST に変換したい例)カレンダーに旅行の予定を登録するUI
帰りの飛行機は現地時刻(PST)で14:00「時差何時間だっけ。。」「この時期ってサマータイム?」「OSの設定変えたくないよ><」
JavaScript Date では解決できない!
環境によって日時がずれるケース
// OSのタイムゾーンをPST(太平洋標準時)に設定して // 2006年4月2日 午前1時 (PST) のタイムスタンプをチェック
var dt = new Date(2006,3,2,1,0,0,0); if (1143968400000 === dt.getTime()) { alert( "OK" ); } else { alert( "NG" ); }
結果
Firefox Chrome Safari Opera IE
Windows NG NG NG NG NG
Mac OK OK NG NG -
Linux OK OK - NG -
iPhone - - NG NG -
Android - OK - - -
なんでズレたの?
PDT(太平洋夏時間)の期間が2006年から2007年にかけて変更されたから
夏時間の期間が約1ヶ月後ろにずれた2006-04-02 01:00:00 は歴史的には夏時間ただし、新ルールで計算し直すと標準時
夏時間の対応レベル
Lv.1 ルールベース毎年同じ夏時間ルールを適用
例)毎年3月第2日曜午前2時から夏時間Windows
Lv.2 ヒストリカルデータ過去の時差情報を利用して時差計算
いわゆる zoneinfo, tz database.世界の秩序は Olson さんがローカルで管理してる!Linux, Java, Python, Ruby...
ブラジルにルールなんてない!
ブラジルは夏時間期間を毎年都度発表ネパールは +5:45(1986年までは +5:40)
ECMAScript ではどうなってるの?
15.9.1.8 Daylight Saving Time AdjustmentECMAScriptの実装としては、同じルールを毎年適用する。でもホスト環境が年ごとの夏時間情報を提供する場合は、それを利用してもいいよ。
つまり、環境と実装に依存
ということで、
OSに依存せずタイムゾーンを選択OSに依存せず時差計算ヒストリカルデータ対応
こんなことをやりたいな。
アプリ開発言語としての JS
Webサイトのクライアント側、じゃなくてHTML5 = オフラインアプリケーションサーバーアクセス無しで動きたい ECMAScript の Date では不十分
ActionScript はどうしてるんだろう
あった。
Google Closure Library
あれ?肝心のデータが。
URLが。。
データ生成する
せっかくなので Rhino 使ってみたタイムゾーンデータは Joda Time(手抜き)JSONフォーマットに変換
tzdata['America/LosAngeles'] = { 'transitions': [ // 遷移時刻タイムスタンプ(時間)と標準からの時差(分)の配列 2770, 60, 7137, 0, 11506, 60, 16041, 0, ... 580186, 60, 585897, 0, 588922, 60, 594633, 0 ], // 標準時の短縮名、正式名、夏時間の短縮名、正式名 'names': ['PST', 'Pacific Standard Time', 'PDT', 'Pacific Daylight Time'], 'id': 'America/Los_Angeles', // ID 'std_offset': -480 // 標準時差};
生成したタイムゾーンデータ
1970年 - 2038年全558地域358 KBWebアプリならアプリケーションキャッシュを使うか、ファイルを分割して遅延ローディングが良さそう。
あれ?
goog.i18n.TimeZone には localToUTC なメソッドがないgoog.date.DateTime にもない。タイムゾーンの変換ができない。片手落ち。ので、いくつかの API 追加実装。
goog.i18n.TimeZone.prototype.getUTCMillisFromLocal = function( opt_year, opt_month, opt_date, opt_hours, opt_minutes, opt_seconds, opt_milliseconds) { ... var localMillis = Date.UTC( opt_year, opt_month, opt_date, opt_hours, opt_minutes, opt_seconds, opt_milliseconds); var localDate = new Date(localMillis); var localOffset = this.getOffset(localDate) * 60 * 1000; var adjustedDate = new Date(localMillis + localOffset); var adjustedOffset = this.getOffset(adjustedDate) * 60 * 1000;
if ( localOffset > adjustedOffset ) { var localNext = this.nextTransitions(localMillis + localOffset); var adjustedNext = this.nextTransitions(localMillis + adjustedOffset); if ( localNext !== adjustedNext ) { return localMillis + localOffset; } } return localMillis + adjustedOffset;};
ようやくデモ
デモ画面上の時刻表示を変換する Chrome 拡張ATND の microformats を読み取って、PST(太平洋標準時)に変換します。
まとめ
JS でマルチタイムゾーンを扱うには自前で実装する必要があるよ。標準でなんとかならないかなぁ。Google Closure 使うんじゃなかった。。HTML5 ってなんだっけ。
以上です。ありがとうございました!