Date#formatとNumber#format2007年05月22日 03時52分11秒

.NET Framework風、再び

以前のエントリ「String.format」でやりたいと思っていた、書式指定子のサポートをとりあえずやってみた。

ダウンロード

こちらから。

能書き

元々.NET Frameworkの劣化コピー的な発想なので、DateとNumberに書式指定可能なformatメソッドを追加し、String.formatのプレースホルダに指定した書式指定子をそのまま各クラスのformatに渡すように考えた。

Dateはdateformat.jsを使わせてもらえば楽だったんだけど、クリエイティブ・コモンズのライセンス適用範囲に不安があったので結局自前で実装することにした。 ただし、書式指定文字のエスケープができない、パーサの実装がないなどの面であきらかにdateformat.jsより劣っているのでorz、たいていはそちらを使ったほうがよいと思われる。 (あと、組み込みオブジェクトの拡張が嫌いな場合とか)

なくても実装は可能だったが、prototype.jsを前提に実装したため、prototype.jsを必要とする。完全に確認はしていないが、1.4.0以降なら問題ないはず。

後述の通り、Date#format、Number#formatの実装に加え、String.formatも書式指定子サポートを追加して実装しなおした。

Formattableインターフェイス

Date、Numberとも似たようなことをするので、formatメソッドはFormattableオブジェクトに実装し、Date.prototoyep、Number.prototypeへ重ねるようにした。 また、書式指定子の定義をそれぞれのコンストラクタ関数のメンバ「formatters」として定義し、formatメソッド内からthis.constructor経由で参照させている。 具体的な実装は以下の通り。

var Formattable = {
	defaultFormat : "",
	format : function(format) {
		var formatters = this.constructor.formatters || [];
		
		return formatters.inject( format || this.defaultFormat, function(result, formatter) {
			return result.replace( formatter.pattern, function() {
				return formatter.format.apply( this, [ this ].concat( $A( arguments ) ) );
			}.bind( this ) );
		}.bind( this ) );
	}
}

書式指定子の基本設計

pattern(RegExp)プロパティとformatメソッドをメンバに持つオブジェクトを定義した。

formatメソッドの第一引数はフォーマット対象の値、第二引数以降にpatternプロパティの正規表現でexecした結果が渡される。例えばDate向けの年フォーマットは

{
	pattern : /yyyy|yy|y/,
	format : function(value, pattern) {
		return pattern.length == 1 ?
			value.getFullYear().toString() :
			( "0000" + value.getFullYear() ).slice(-1 * pattern.length);
	}
}
と定義してあり、formatの第二引数patternに一致文字列全体が渡されるので、1文字かそれ以上かを判断して0詰を行うかそのままtoStringするかなどの分岐をしている。

Date、Numberとも同一の設計のフォーマット情報を配列で持たせ、それをループ処理で適用している。

Dateの書式指定子

dateformat.jsに酷似しているが、ミリ秒の指定方法と解釈が若干違う

書式指定子 説明
yyyy、yy、y 年の指定。yyyyは4桁、yyは下2桁、yは桁詰なしになる。
MM、M 月の指定。MMは2桁、Mは桁詰なしになる。
dd、d 日の指定。MMは2桁、Mは桁詰なしになる。
HH、H 時の指定。HHは2桁、Hは桁詰なしになる。常に24時間書式になる。
mm、m 分の指定。mmは2桁、mは桁詰なしになる。
ss、s 秒の指定。ssは2桁、sは桁詰なしになる。
fff、ff、f ミリ秒の指定。桁数はfの桁数に一致し、実際のgetMilliseconds()よりも指定桁数が少ない場合は丸められるが、丸め方は処理系依存になる(みたい。IEとFirefox/Operaで(0.150).toFixed(2)の結果が違う)。

Numberの書式指定子

3桁のカンマ区切り書式、ゼロ詰、および桁数指定の16進数の書式を定義している。

書式指定子 説明
#,##0[.0+] 3桁ごとにカンマで区切る書式で、オプションで小数部を指定できる。小数部は0を必要桁数だけ指定する。例えば小数点以下第4位まで必要な場合は"#,##0.0000"とする。
0+[.0+] 指定桁数分だけ0詰を行う書式。オプションで小数部の指定も可能。整数部の桁数は書式指定子の0の桁数と実際の整数部の桁数の大きいほうが採用される。
x[n]、X[n] 16進数。nで指定した桁数になるようゼロ詰される。xの大文字小文字の違いは9より大きい数のアルファベット文字に反映される。

テスト

Date
Number

宿題

  • パースメソッドの実装 → 今のformattersの定義を流用したいが方法が浮かばないorz
  • Number#formatのパーセント対応 → なくてもいいけど

コメント

コメントをどうぞ

※メールアドレスとURLの入力は必須ではありません。 入力されたメールアドレスは記事に反映されず、ブログの管理者のみが参照できます。

※なお、送られたコメントはブログの管理者が確認するまで公開されません。

名前:
メールアドレス:
URL:
コメント:

トラックバック

このエントリのトラックバックURL: http://dara-j.asablo.jp/blog/2007/05/22/1524688/tb

※なお、送られたトラックバックはブログの管理者が確認するまで公開されません。