JavaScript で書式指定フォーマット
1. はじめに
JavaScriptで、動的に変数を文字列に埋め込む際、テンプレートリテラルが、簡単で良く使われている認識です。
console.log(`v: ${1.5}`); // "v: 1.5";
一方で、書式を指定して値を文字列に変換することがサポートされていないようです。
毎回スクラッチで実装するのは手間なので、(主に自分用に) 実装して公開しました。
(npmの事を良くわかっていないのでパッケージングしていません。今だったらJSRがいいんですかね。)
2. 使い方
Python の f-string のような書式指定文字列化と、date コマンドのような書式指定文字列化の大きく2つの書式を提供しています。
また、両方にそのまま使えるデフォルトの formatter と、カスタムできる仕組みを用意しています。
2.1 f-string like
疑似シンタックス: {index[:[[align]width][.precision]type]}
単一のメッセージテンプレートに複数の値を差し込む形式
2.1.1 デフォルト
import { format } from "https://cdn.jsdelivr.net/gh/ymd-h/format-js/format.js";
format("{0} + {1} = {2}", 1, 2, 1+2); // "1 + 2 = 3"
format("Precision: {0:.2f}", 1.78); // "Precision: 1.78"
format("Width: {0:4d}", 1); // "Width: 1"
format("Hex: {0:x}", 15); // "Hex: f"
format("Align: {0:<4d}", 1); // "Align: 1 "
2.1.2 パッチによる微修正
新しく、精度情報も表示する w
書式と、余ったスペースに *
を詰める *
配置を追加してみた例
import { patch_default_format } from "https://cdn.jsdelivr.net/gh/ymd-h/format-js/format.js";
const f = patch_default_format(
{ // key: (value: *, precision: number) => formatted_string
"w": (value, precision) => value.toFixed(precision) + ` (${precision})`,
}, // Patch for Format Handlers (optional)
{ // key: (value: string, width: number) => aligned_string
"*": (value, width) => value.padStart(width, "*"),
}, // Patch for Align (optional)
);
f.format("{0:.2w}", 1); // "1.00 (2)"
f.format("{0:.6w}", 1.25); // "1.000000 (6)"
f.format("{0:*6.2f}", 1); // "**1.00"
2.1.3 フルスクラッチ
完全にスクラッチで formatter を構築する例。
省略していますが、 handlers
/ align
に指定できる内容は、2.1.2のパッチと同じです。
その他に、固定浮動小数点のデフォルト精度をオプションで指定できます。
import { FStringLikeFormatter } from "https://cdn.jsdelivr.net/gh/ymd-h/format-js/format.js";
const f = new FStringLikeFormatter(
{
...
}, // handlers
{
...
}, // align
{ defaultPrecision: 2 }, // options (optional)
);
f.format("My name is {0}.", "ymd-h");
2.2 date like
%
に続けて書式を指定します。
単一のメッセージテンプレートに単一の値 (通常はDate
) を差し込む形式。
2.2.1 デフォルト
import { format_date } from "https://cdn.jsdelivr.net/gh/ymd-h/format-js/format.js";
format_date("%Y-%m-%d %H:%M:%S", new Date(2024, 2, 24, 18, 44, 52)); // "2024-03-24 18:44:52"
format_date("%T", new Date(2024, 2, 24, 18, 44, 52)); // "18:44:52"
2.2.2 パッチによる微修正
p
の表記を a.m.
/ p.m.
に上書きしてみた例
import { patch_default_formatformat_date } from "https://cdn.jsdelivr.net/gh/ymd-h/format-js/format.js";
const f = patch_default_formatformat_date({
"p": d => (d.getHours() < 12) ? "a.m." : "p.m.",
});
f.format("%p", new Date(2024, 2, 24, 18, 44, 52)); // "p.m."
2.2.3 フルスクラッチ
完全にスクラッチで作成する例。
この方式であれば、 Date
以外への対応も可能
import { DateLikeFormatter } from "https://cdn.jsdelivr.net/gh/ymd-h/format-js/format.js";
const f = new DateLikeFormatter({
"p": d => (d.getHours() < 12) ? "a.m." : "p.m.",
});
f.format("%p", new Date(2024, 2, 24, 18, 44, 52)); // "p.m."
3. デフォルト formatter に定義済みの書式・配置
3.1 f-String like
format | description |
---|---|
s |
文字列 (.toString() ) |
b |
2進数 |
c |
ユニコード文字 (String.fromCodePoint() ) |
d |
整数 (10進数) |
o |
8進数 |
x |
16進数。a -f を利用 |
X |
16進数。A -F をを利用 |
e |
科学的表記 (指数表記)。基数に e を利用 |
E |
科学的表記 (指数表記)。基数に E を利用 |
f |
固定浮動小数点表記。nan / infinity を利用 |
F |
固定浮動小数点表記。NAN / INFINITY を利用 |
% |
パーセント (百分率) 表記。 (100を掛けた固定浮動小数点表記に % ) |
align | description |
---|---|
< |
左詰め |
^ |
真ん中寄せ |
> / (empty) |
右詰め (default) |
3.2 date like
format | description |
---|---|
%y |
世紀なし年 (2桁) |
%Y |
年 (4桁) |
%m |
月 (01 - 12 ) |
%d |
日 (01 - 31 ) |
%H |
時 (24時間表記) (00 - 23 ) |
%I |
時 (12時間表記) (01 - 12 ) |
%p |
AM or PM
|
%M |
分 (00 - 59 ) |
%S |
秒 (00 - 59 ) |
%f |
ミリ秒 (000 - 999 ) |
%s |
Unix Time。 1970-01-01 00:00:00 UTC からの経過秒 |
%T |
%H:%M:%S と同じ |
%w |
曜日の数字表記。 日曜が 0 。 (0 - 6 ) |
%% |
% (エスケープ) |
4. 実装
実装は、正規表現 (RegExp
) を用いて、 String.prototype.replaceAll(pattern, replacement)
(MDN) で差し替える実装です。
この2つ目の引数 replacement
には関数を指定することができるため、この関数で書式に応じた変換を行っています。
さっと使えるデフォルトとユーザーによるカスタマイズを両立させるために、正規表現を保持するクラスを作り、デフォルトインスタンスを用意すると伴に、パッチによる微修正ができるようにしました。
5. まとめ
JavaScript で書式指定文字列化をする format.js を実装して公開しました。
もし興味を持ってくれた人がいたら使ってみたり、コードを読んでみたり、レポジトリにスターつけたりしてくれると嬉しいです。
Discussion