Intl.DurationFormat:JavaScriptにおける時間間隔表現の次世代標準
Webアプリケーションにおいて、期間(Duration)をユーザーフレンドリーな形式で表示することは、長年の課題でした。「2時間15分」や「5分30秒」といった情報を、多言語対応かつ正確にフォーマットするためには、これまで開発者が独自にロジックを組むか、Moment.jsやdate-fnsといった重厚なライブラリに依存する必要がありました。
しかし、TC39によって提案され、主要ブラウザで実装が進んでいる「Intl.DurationFormat」は、この状況を一変させます。本記事では、この強力なAPIの仕組み、実務での活用方法、そして既存のライブラリからの移行戦略について、シニアWebデザイナーの視点から深く解説します。
Intl.DurationFormatの概要と意義
Intl.DurationFormatは、ECMAScriptのInternationalization APIの一部として提供される新しいオブジェクトです。その最大の目的は、期間を表すデータ構造を、特定のロケール(言語や地域)の慣習に従って人間が読みやすい文字列に変換することにあります。
従来、JavaScriptには期間を扱うネイティブな型が存在せず、Dateオブジェクトで代用したり、ミリ秒単位の数値を手動で計算したりしていました。この手法には、「1時間=60分」といった単位変換のロジックを各言語の翻訳ファイルに含めなければならないという大きなコストがありました。Intl.DurationFormatは、ブラウザが持つネイティブなロケールデータベースを利用することで、これらの複雑な処理を単一のAPIで完結させます。
詳細解説:仕組みとパラメータの制御
Intl.DurationFormatのコンストラクタは、第一引数にロケール、第二引数にオプションオブジェクトを受け取ります。このオプションが非常に柔軟で、表示する単位の取捨選択や、数値の表示形式を細かく制御可能です。
主要な制御パラメータは以下の通りです:
1. style: 期間の表示スタイルを指定します。「long」(2時間15分)、「short」(2h 15m)、「narrow」(2h 15m)が選択可能です。
2. numberingSystem: 数字の表記体系(アラビア数字、漢数字など)を指定します。
3. style(単位ごと): 各単位(years, months, weeks, days, hours, minutes, seconds, milliseconds)に対して、個別に表示・非表示やスタイルの指定が可能です。
このAPIの強みは、単なる変換ではなく「文脈」を理解している点にあります。例えば、英語圏では「2 hours, 15 minutes」とカンマで区切るのが一般的ですが、他言語では異なる区切り文字や接続詞が使われます。これら全てをブラウザ側で自動処理できるため、開発者は「どの単位を表示するか」というビジネスロジックに集中できるのです。
サンプルコード:実践的な実装パターン
以下に、Intl.DurationFormatを用いた具体的な実装例を示します。
// 期間データの定義
const duration = {
hours: 2,
minutes: 15,
seconds: 30
};
// 1. 基本的なフォーマット(デフォルト)
const dfLong = new Intl.DurationFormat('ja-JP', { style: 'long' });
console.log(dfLong.format(duration));
// 出力: "2時間15分30秒"
// 2. 短縮形式での表示
const dfShort = new Intl.DurationFormat('en-US', { style: 'short' });
console.log(dfShort.format(duration));
// 出力: "2h 15m 30s"
// 3. 特定の単位のみを表示するカスタマイズ
const dfCustom = new Intl.DurationFormat('ja-JP', {
style: 'long',
hours: 'numeric',
minutes: 'numeric',
seconds: 'numeric'
});
console.log(dfCustom.format({ hours: 1, minutes: 30 }));
// 出力: "1時間30分"
// 4. ゼロ値の制御(表示するか否か)
const dfZero = new Intl.DurationFormat('en-US', {
style: 'long',
hours: 'numeric',
minutes: 'numeric',
seconds: 'numeric'
});
console.log(dfZero.format({ hours: 0, minutes: 5, seconds: 0 }));
// 出力: "5 minutes"
実務アドバイス:導入時の注意点とベストプラクティス
実務の現場でIntl.DurationFormatを採用する際、いくつかの重要なポイントがあります。
まず、「ポリフィルの選定」です。現在、すべてのブラウザがこの仕様を完璧に実装しているわけではありません。特にレガシーブラウザをサポートする必要があるプロジェクトでは、`@formatjs/intl-durationformat`のようなポリフィルを導入することが必須です。ビルド環境(WebpackやVite)で適切に条件分岐させ、モダンブラウザではネイティブAPIを使い、そうでない場合にのみポリフィルを読み込む構成にすることで、バンドルサイズを最小限に抑えられます。
次に、「デザインシステムとの統合」です。UIパーツとして期間表示をコンポーネント化する際、単に値を渡すのではなく、`displayStyle`(long/short/narrow)をPropsとして受け取れるように設計してください。これにより、ダッシュボードの狭いスペースには `narrow` を、詳細ページでは `long` をといった使い分けが容易になります。
また、非同期でデータを取得する場合の「ローディング状態」にも気を配りましょう。期間の計算にはサーバー側のタイムスタンプとの差分が必要になることが多いですが、フロントエンドで計算を行う場合は、クライアントの時計のズレに注意が必要です。可能であれば、期間(Duration)そのものをAPIのレスポンスとして受け取り、フォーマッタに渡すのが最も安全です。
パフォーマンスとアクセシビリティへの配慮
Intl.DurationFormatは、非常に高速に動作するように設計されています。しかし、大量のリスト(例えば、数千件のログデータの時間表示など)で毎秒フォーマット処理を行うと、メインスレッドをブロックする可能性があります。このような場合は、`Intl.DurationFormat`インスタンスを一度生成し、キャッシュして再利用するようにしてください。
アクセシビリティの観点からは、`aria-label`の活用が重要です。「2h 15m」という表記は視覚的には分かりやすいですが、スクリーンリーダーが「2エイチ、15エム」と読み上げてしまうリスクがあります。`Intl.DurationFormat`で生成した文字列をそのまま出力するのではなく、可能であれば `aria-label=”2時間15分”` といった補足情報を付与することで、アクセシビリティを担保してください。
まとめ
Intl.DurationFormatは、これまで開発者を悩ませてきた「多言語対応の時間表示」という課題を劇的に簡素化する強力なツールです。標準APIとして提供されることで、ライブラリの依存関係を減らし、アプリケーションの保守性を向上させることができます。
Webデザイナーとして、またエンジニアとして、私たちは「ユーザーにとって分かりやすい情報提示」を追求する責任があります。ブラウザが提供する強力な機能を最大限に活用し、軽量で、かつ世界中のユーザーに等しく価値を届けるインターフェースを構築していきましょう。今後、このAPIはWeb標準のデファクトスタンダードとして定着していくことは間違いありません。今のうちに習得し、次世代のフロントエンド開発の武器として活用してください。

コメント