経過時間表示に小数秒を含める方法

フォーマット済み時間に1秒未満の精度を表示する

はじめに

経過時間を1秒未満の精度で表示したい場合、小数秒を見せる必要があります。ストップウォッチなら「1.234秒」、パフォーマンスプロファイラでは「0.853秒」、レースタイマーでは「45.678秒」といった形です。フォーマットを適切にしないと、次のようなコードを書きがちです。

const seconds = 1.234;
const duration = `${seconds}s`;

これだと、小数点はハードコードされているので「1.234s」と表示されます。しかし、フランスのユーザーは小数点としてカンマ(,)が期待されているため「1,234 s」のように表示されるのが自然です。ロケールによって、小数点や区切り文字のルールは異なります。

JavaScriptでは、fractionalDigits オプションを Intl.DurationFormat で指定することで、小数秒の表示方法をコントロールできます。このレッスンでは、経過時間表示に小数秒を追加する方法と、その精度の調整について解説します。

小数秒とは

小数秒とは、1秒未満の時間のことです。たとえば1.5秒なら「1秒半」、0.250秒なら「4分の1秒」です。

小数秒の主な形式は3つあります:

  • ミリ秒(千分の1秒 : 0.001秒)
  • マイクロ秒(百万分の1秒 : 0.000001秒)
  • ナノ秒(十億分の1秒 : 0.000000001秒)

fractionalDigits オプションで、小数点以下に何桁表示するかを制御できます。fractionalDigits: 3 に設定するとミリ秒の精度、fractionalDigits: 6 に設定するとマイクロ秒の精度となります。

小数秒なしで経過時間をフォーマットする

デフォルトでは、経過時間は小数点以下なし(整数秒)で表示されます。

const duration = { hours: 0, minutes: 0, seconds: 1 };

new Intl.DurationFormat('en', { style: 'long' }).format(duration);
// "1 second"

new Intl.DurationFormat('en', { style: 'digital' }).format(duration);
// "0:00:01"

ミリ秒を別の単位として指定した場合も、小数秒としてではなく、独立した単位として表示されます。

const duration = { seconds: 1, milliseconds: 234 };

new Intl.DurationFormat('en', { style: 'long' }).format(duration);
// "1 second and 234 milliseconds"

これは2つの単位を別々に表示します。「1.234秒」のように表示する場合は、fractionalDigits オプションが必要です。

秒数に小数を追加する

fractionalDigits オプションは、秒の小数点以下の桁数を指定します。このオプションを設定すると、小数秒を結果に含めることができます。

const duration = { seconds: 1.234 };

new Intl.DurationFormat('en', {
  style: 'long',
  fractionalDigits: 3
}).format(duration);
// "1.234 seconds"

APIは整数部と小数部をロケールに合わせた小数点で1つの形式にまとめて表示します。

小数秒の精度を指定する

fractionalDigits オプションには0から9までの値を指定できます。これで小数点以下に表示する桁数が決まります。

const duration = { seconds: 1.23456789 };

new Intl.DurationFormat('en', {
  style: 'long',
  fractionalDigits: 0
}).format(duration);
// "1 second"

new Intl.DurationFormat('en', {
  style: 'long',
  fractionalDigits: 2
}).format(duration);
// "1.23 seconds"

new Intl.DurationFormat('en', {
  style: 'long',
  fractionalDigits: 4
}).format(duration);
// "1.2346 seconds"

new Intl.DurationFormat('en', {
  style: 'long',
  fractionalDigits: 6
}).format(duration);
// "1.234568 seconds"

指定した精度よりも値の桁数が少ない場合、フォーマッターはゼロで埋め合わせます。

const duration = { seconds: 1.5 };

new Intl.DurationFormat('en', {
  style: 'long',
  fractionalDigits: 4
}).format(duration);
// "1.5000 seconds"

丸め処理が必要な場合、フォーマッターは切り捨て(ゼロ方向への丸め)で表示します。

const duration = { seconds: 1.9999 };

new Intl.DurationFormat('en', {
  style: 'long',
  fractionalDigits: 2
}).format(duration);
// "1.99 seconds"

デジタル形式で小数秒を使う

デジタル形式はタイマーのようにコロンで区切って表示します。小数秒は秒の後ろに表示されます。

const duration = { hours: 2, minutes: 30, seconds: 12.345 };

new Intl.DurationFormat('en', {
  style: 'digital',
  fractionalDigits: 3
}).format(duration);
// "2:30:12.345"

new Intl.DurationFormat('en', {
  style: 'digital',
  fractionalDigits: 2
}).format(duration);
// "2:30:12.34"

この方法はデジタル形式の単位組み合わせならどれでも利用できます。

const duration = { minutes: 5, seconds: 30.678 };

new Intl.DurationFormat('en', {
  style: 'digital',
  fractionalDigits: 3
}).format(duration);
// "5:30.678"

ロケールごとの小数秒書式

ロケールによって小数点の区切り方が異なります。英語はピリオド、多くのヨーロッパ言語はカンマを使います。

const duration = { seconds: 1.234 };

new Intl.DurationFormat('en', {
  style: 'long',
  fractionalDigits: 3
}).format(duration);
// "1.234 seconds"

new Intl.DurationFormat('fr', {
  style: 'long',
  fractionalDigits: 3
}).format(duration);
// "1,234 seconde"

new Intl.DurationFormat('de', {
  style: 'long',
  fractionalDigits: 3
}).format(duration);
// "1,234 Sekunden"

new Intl.DurationFormat('ar', {
  style: 'long',
  fractionalDigits: 3
}).format(duration);
// "١٫٢٣٤ ثانية"

APIはロケールごとに正しい小数点、数字、スペースを自動で使い分けます。

ストップウォッチ用の時刻フォーマット

ストップウォッチアプリでは、経過時間を小数秒まで表示する必要があります。小数秒付きのデジタル形式を使ってください。

function formatStopwatchTime(totalSeconds) {
  const minutes = Math.floor(totalSeconds / 60);
  const seconds = totalSeconds % 60;

  const duration = { minutes, seconds };
  const locale = navigator.language;

  return new Intl.DurationFormat(locale, {
    style: 'digital',
    fractionalDigits: 2
  }).format(duration);
}

formatStopwatchTime(65.47);
// "1:05.47"

formatStopwatchTime(123.89);
// "2:03.89"

これは、センチ秒単位の精度のために小数点以下2桁で「1:05.47」のような時刻を表示します。

レースのゴールタイムをフォーマットする

スポーツの計時システムでは、高精度なゴールタイムが表示されます。リザルトにはミリ秒単位の精度を使用しましょう。

function formatRaceTime(totalSeconds, locale) {
  const minutes = Math.floor(totalSeconds / 60);
  const seconds = totalSeconds % 60;

  const duration = { minutes, seconds };

  return new Intl.DurationFormat(locale, {
    style: 'digital',
    fractionalDigits: 3
  }).format(duration);
}

formatRaceTime(125.678, 'en');
// "2:05.678"

formatRaceTime(125.678, 'fr');
// "2:05,678"

小数点以下3桁がミリ秒単位の正確なレース計時を表します。

パフォーマンス測定値のフォーマット

パフォーマンスプロファイラでは、ロード時間や実行時間を1秒未満の単位で表示します。小数点以下の秒で短いフォーマットを使いましょう。

function formatLoadTime(seconds, locale) {
  const duration = { seconds };

  return new Intl.DurationFormat(locale, {
    style: 'short',
    fractionalDigits: 3
  }).format(duration);
}

formatLoadTime(0.853, 'en');
// "0.853 sec"

formatLoadTime(2.145, 'en');
// "2.145 sec"

これは、パフォーマンス測定値をミリ秒単位でコンパクトに表示します。

動画フレームのタイムスタンプをフォーマットする

動画編集アプリではフレーム単位で正確なタイムスタンプが表示されます。フレームレートに応じた小数点以下の秒を使用します。

function formatVideoTimestamp(totalSeconds, locale) {
  const hours = Math.floor(totalSeconds / 3600);
  const minutes = Math.floor((totalSeconds % 3600) / 60);
  const seconds = totalSeconds % 60;

  const duration = hours > 0
    ? { hours, minutes, seconds }
    : { minutes, seconds };

  return new Intl.DurationFormat(locale, {
    style: 'digital',
    fractionalDigits: 2
  }).format(duration);
}

formatVideoTimestamp(125.67, 'en');
// "2:05.67"

formatVideoTimestamp(3665.42, 'en');
// "1:01:05.42"

これは100fpsの動画でフレーム単位の精度でタイムスタンプを表示します。

ミリ秒を小数秒に変換する

時間計算ではしばしばミリ秒が得られます。ミリ秒を1000で割って小数秒に変換します。

const milliseconds = 1234;
const totalSeconds = milliseconds / 1000;

const duration = { seconds: totalSeconds };

new Intl.DurationFormat('en', {
  style: 'long',
  fractionalDigits: 3
}).format(duration);
// "1.234 seconds"

これは整数のミリ秒を小数の秒値に変換します。

非常に短い時間の扱い

1秒未満の持続時間の場合、秒単位のみを小数点以下の桁と一緒に表示します。

const duration = { seconds: 0.045 };

new Intl.DurationFormat('en', {
  style: 'short',
  fractionalDigits: 3
}).format(duration);
// "0.045 sec"

小数点の前のゼロは、1秒未満であることを示します。

ユースケースに合わせて精度を選ぶ

用途によって必要な精度は異なります:

  • ストップウォッチ:小数2桁(センチ秒)
  • スポーツ計時:小数3桁(ミリ秒)
  • パフォーマンス計測:小数3桁(ミリ秒)
  • 科学測定:小数6〜9桁(マイクロ秒〜ナノ秒)

用途に合ったfractionalDigits値を設定してください。

const duration = { seconds: 1.23456789 };
const locale = navigator.language;

// For general timing
new Intl.DurationFormat(locale, {
  style: 'digital',
  fractionalDigits: 2
}).format(duration);
// "0:00:01.23"

// For precise measurements
new Intl.DurationFormat(locale, {
  style: 'short',
  fractionalDigits: 6
}).format(duration);
// "1.234568 sec"

測定システムが提供できる以上の精度を表示しないようにしましょう。

必要ない場合は小数秒を省略する

全秒のみを小数なしで表示するには、fractionalDigits: 0 を設定します。

const duration = { seconds: 1.7 };

new Intl.DurationFormat('en', {
  style: 'long',
  fractionalDigits: 0
}).format(duration);
// "1 second"

これにより値が丸められ、整数部分のみが表示されます。

小数秒対応のフォーマッターを再利用する

特定の小数点以下の精度をもつフォーマッターの作成も、他のフォーマッターと同じくパフォーマンス最適化の考え方に従います。

const formatter = new Intl.DurationFormat('en', {
  style: 'digital',
  fractionalDigits: 3
});

const times = [
  { minutes: 1, seconds: 5.234 },
  { minutes: 2, seconds: 15.678 },
  { minutes: 0, seconds: 45.901 }
];

times.map(t => formatter.format(t));
// ["1:05.234", "2:15.678", "0:45.901"]

これにより、複数の期間をフォーマットする際にフォーマッターのインスタンスを再利用でき、パフォーマンスが向上します。

ブラウザーサポート

fractionalDigits オプションは Intl.DurationFormat API の一部であり、2025年3月にBaselineとなりました。Chrome、Edge、Firefox、Safariの最新バージョンで動作します。

小数秒を使用する前に対応状況を確認しましょう。

if (typeof Intl.DurationFormat !== 'undefined') {
  const formatter = new Intl.DurationFormat('en', {
    style: 'digital',
    fractionalDigits: 3
  });
  return formatter.format(duration);
} else {
  return `${duration.minutes}:${duration.seconds.toFixed(3)}`;
}

これにより、利用可能な場合はネイティブAPIを使いつつ、古いブラウザー向けにフォールバックも提供できます。