Edited at

JavaScriptで数値フォーマットする標準API「Intl.NumberFormat」 (カンマ区切り、円・ドル表記、漢数字など)

More than 1 year has passed since last update.

ほぼすべてのブラウザやNode.jsでサポートされている数値をフォーマットするAPI「Intl.NumberFormat」を紹介する記事です。

JavaScriptで数値をカンマ区切りにしたいときにGoogleで検索してみると、正規表現を使っていたり、ループで回して3桁ごとにカンマ付ける実装を紹介する記事を多く見つけました。

しかし、それらは古い記事ということもあり、2018年現在は数値のフォーマットを実装する必要はありません。EcmaScriptで仕様策定されておりほとんどのブラウザやNode.jsで使える関数があるので紹介します。

今回紹介するコードの実行結果はすべてChromeでの結果になります。


TL;DR


Intl

i18nやl10nといった国際化対応するためのAPIです。

詳しくは「Intl - JavaScript|MDN」をお読みください。

EcmaScriptの仕様については「ここ」を読んで下さい。


Intl.NumberFormat

通過や文字など国や地域によって数の表記は違います。このAPIはその国ごとの表記を指定した表記に変換してくれるAPIを提供してくれるオブジェクトです。

詳しくはMDNの記事をお読み下さい。日本語の記事は情報が古いので英語版を参考にしてください。

以下のようにlocaleをコンストラクタの引数に指定することができます。

引数の指定が無い場合は'us-EN'が設定されます。

const formatter = new Intl.NumberFormat('ja-JP');


Intl.NumberFormat.prototype.format

数値を変換する関数です。Intl.NumberFormatのメソッドです。

IEを含むほぼすべてのブラウザで使用可能です。

よく使われそうな例を紹介します。


カンマ区切り

冒頭で説明したカンマ区切りです。3桁ごとに区切って表示する場合に使うことができます。

以下は'ja-JP'を指定していますが、'us-EN'や引数なしでも同じように3桁でカンマ区切りします。

const formatter = new Intl.NumberFormat('ja-JP');

formatter.format(1000);
// => "1,000"


通貨

数値をサクッと円やドル表記したいことはあると思います。

円の表記は以下のようにNumberFormatの第2引数にオブジェクトを渡すことで実現可能です。

第2引数のオプションについてもやはりMDNの「Intl.NumberFormat」に詳しく載っていますので興味ある方はそちらをお読み下さい。

const formatter = new Intl.NumberFormat('ja-JP', {

style: 'currency',
currency: 'JPY'
});
formatter.format(1000);
// => "¥1,000"

もちろん、ドルやユーロなども対応しています。

let formatter = new Intl.NumberFormat('us-EN', {

style: 'currency',
currency: 'USD'
});
formatter.format(1000);
// => "$1,000.00"

let formatter = new Intl.NumberFormat('de-DE', {
style: 'currency',
currency: 'EUR'
});
formatter.format(1000)
// => "1.000,00 €"


漢数字

数値を漢数字の文字列に変換することも可能です。

以下は「中国で使用される簡体字で書かれる中国語の10進数の漢数字」という指定をしています。

zh-Hans-CNまでが「中国で使用される簡体字で書かれる中国語」を指し、u-nu-hanidecが「10進数の漢数字」を指します。

const formatter = new Intl.NumberFormat('zh-Hans-CN-u-nu-hanidec');

formatter.format(1234567890);
// => "一,二三四,五六七,八九〇"


Intl.NumberFormat.prototype.formatToParts

上記のようにformat関数で数値のフォーマットが行えますが、新しいAPIであるformatToPartsに関しても紹介しておきます。

執筆時点(2018/04/15)ではChrome63とFirefox58で使えるようになっています。

Node.jsも次期バージョンのv10では使えます。

EcmaScriptの仕様は「ここ」にあります。

数値のカスタムフォーマットを行うことが可能になります。

formatToPartsの戻り値は{type: string, value: string}のオブジェクトの配列です。

const formatter = new Intl.NumberFormat('ja-JP', {

style: 'currency',
currency: 'JPY'
});
formatter.formatToParts(1000);
// => [ { type: 'currency', value: '¥' },
// { type: 'integer', value: '1' },
// { type: 'group', value: ',' },
// { type: 'integer', value: '000' } ]

オブジェクトの配列なので、あとは好き勝手いじることが可能です。

以下はMDNに掲載されている例をJPYにしてみた例です。

const num = 1000;

const formatter = new Intl.NumberFormat('ja-JP', {
style: 'currency',
currency: 'JPY'
});
const yen = formatter.formatToParts(num).map(({type, value}) => {
switch (type) {
case 'currency': return "<strong>" + value + "</strong>";
default: return value;
}
}).reduce((string, part) => {return string + part});
console.log(yen);
// => "<strong>¥</strong>1,000"


最後に

数値のフォーマット関数は標準で用意されているAPIを使いましょう。


補足(2018/04/17)

はてブでSafariで使えないというコメントがあったので補足します。

Intl.NumberFormat.prototype.formatはSafari10から対応しています。

Intl.NumberFormat.prototype.formatToPartsは使えません。

MDNの日本語版のブラウザ対応表が更新されていませんでした。英語版では10から対応と記載がありました。Safari11.1でも確認済みです。

また、MDNのIntl.NumberFormat.prototype.formatの日本語版のSafariのサポートバージョンも更新しておきました。


参考

最後までお読みいただきありがとうございました。不備や質問がございましたらコメント欄に記載またはTwitterで @shisama_ 宛にメンション飛ばして下さい。