Intl.DateTimeFormat.prototype.formatToParts()

Intl.DateTimeFormat.prototype.formatToParts() メソッドは、ロケールを考慮した Intl.DateTimeFormat フォーマッターが生成する文字列のロケールを考慮した書式化を可能にします。

試してみましょう

構文

js
formatToParts(date);

引数

date 省略可

書式化する日付。

返値

Array で、書式化された日付のパーツを含むオブジェクトの配列です。

解説

formatToParts() メソッドは、日付文字列のフォーマットをカスタマイズするときに役立ちます。これは、ロケール特有の部分を保持しながら、カスタム文字列を構築できるロケール特有のトークンを含むオブジェクトの Array を返します。formatToParts() メソッドが返却する構造は、このようになります。

js
[
  { type: "day", value: "17" },
  { type: "weekday", value: "Monday" },
];

渡される可能性がある type は以下のとおりです。

day

日付として使用される文字列。たとえば、 "17"。

dayPeriod

日付期間として使用される文字列。たとえば、 "AM", "PM", "in the morning", "noon" など。

era

時代として使用される文字列。たとえば、"BC" や "AD"。

fractionalSecond

小数点以下の秒として使用される文字列です。例えば "0" や "00" や "000" です。

hour

時刻として使用される文字列。たとえば "3" や "03"。

literal

日付や時刻の区切りとして使用される文字列。たとえば "/"、","、"o'clock"、"de"。

minute

分として使用される文字列。たとえば、"00"。

month

月として使用される文字列。たとえば、"12"。

relatedYear

カレンダーの表現が year ではなくyearNameである場合、関連する4桁のグレゴリオ暦の年に使用される文字列です。例えば "2019" です。

second

秒として使用される文字列。たとえば、"07" や "42"。

timeZoneName

タイムゾーン名として使用される文字列。たとえば、"UTC"。

weekday

曜日として使用される文字列。たとえば、"M" や "Monday"、"Montag"。

year

年として使用される文字列。たとえば、"2012" や "96"。

yearName

関連するコンテキストで yearName に使用される文字列、例えば "geng-zi" など。

ポリフィル

この機能のポリフィルは、提案リポジトリーから利用できます。

DateTimeFormat は、直接操作できないローカライズされた透過的でない文字列を出力します。

js
var date = Date.UTC(2012, 11, 17, 3, 0, 42);

var formatter = new Intl.DateTimeFormat("en-us", {
  weekday: "long",
  year: "numeric",
  month: "numeric",
  day: "numeric",
  hour: "numeric",
  minute: "numeric",
  second: "numeric",
  fractionalSecondDigits: 3,
  hour12: true,
  timeZone: "UTC",
});

formatter.format(date);
// "Monday, 12/17/2012, 3:00:42.000 AM"

しかし、多くのユーザーインターフェイスでは、この文字列の書式をカスタマイズしたいという要望があります。 formatToParts メソッドは、文字列を部品単位で提供することで、 DateTimeFormat フォーマッターによって生成された文字列のロケールを意識した書式設定ができるようになります。

js
formatter.formatToParts(date);

// return value:
[
  { type: "weekday", value: "Monday" },
  { type: "literal", value: ", " },
  { type: "month", value: "12" },
  { type: "literal", value: "/" },
  { type: "day", value: "17" },
  { type: "literal", value: "/" },
  { type: "year", value: "2012" },
  { type: "literal", value: ", " },
  { type: "hour", value: "3" },
  { type: "literal", value: ":" },
  { type: "minute", value: "00" },
  { type: "literal", value: ":" },
  { type: "second", value: "42" },
  { type: "fractionalSecond", value: "000" },
  { type: "literal", value: " " },
  { type: "dayPeriod", value: "AM" },
];

これで情報は個別に利用可能になり、カスタマイズされた方法で再び書式化して連結することができます。例えば、Array.prototype.map()アロー関数switch 文テンプレートリテラルArray.prototype.join() などを使用しています。

js
var dateString = formatter
  .formatToParts(date)
  .map(({ type, value }) => {
    switch (type) {
      case "dayPeriod":
        return `<b>${value}</b>`;
      default:
        return value;
    }
  })
  .join("");

これにより、 formatToParts() メソッドを使用する際に、日の部分が太字になります。

js
console.log(formatter.format(date));
// "Monday, 12/17/2012, 3:00:42.000 AM"

console.log(dateString);
// "Monday, 12/17/2012, 3:00:42.000 <b>AM</b>"

名前付きの年と混合カレンダー

名前付きの年を使用している暦もあります。例えば、中国やチベットの暦では、 60 年周期の干支を使用しています。これらの年は、グレゴリオ暦の年と関連付けて識別されます。このような場合、 formatToParts() の結果は、通常は年が存在するはずなのに、年の項目ではなく、 4 桁のグレゴリオ暦の年を含む relatedYear の項目を含むことになります。バッグの中の項目を (任意の値で) year に設定すると、年と yearName グレゴリオ暦の relatedYear の両方が得られます。

js
let opts = { year: "numeric", month: "numeric", day: "numeric" };
let df = new Intl.DateTimeFormat("zh-u-ca-chinese", opts);
df.formatToParts(Date.UTC(2012, 11, 17, 3, 0, 42));

// return value
[
  { type: "relatedYear", value: "2012" },
  { type: "literal", value: "年" },
  { type: "month", value: "十一月" },
  { type: "day", value: "4" },
];

year オプションがバッグ内で設定されていない場合 (任意の値に設定されている場合)、結果には relatedYear のみが含まれます。

js
let df = new Intl.DateTimeFormat("zh-u-ca-chinese");
df.formatToParts(Date.UTC(2012, 11, 17, 3, 0, 42));

// 返値
[
  { type: "relatedYear", value: "2012" },
  { type: "literal", value: "年" },
  { type: "month", value: "十一月" },
  { type: "day", value: "4" },
];

year を出力したい場合は、 .format() は一般的にこれらを並べて表示することができます。

js
let df = new Intl.DateTimeFormat("zh-u-ca-chinese", {year: "numeric"});
df.format(Date.UTC(2012, 11, 17, 3, 0, 42));

// 返値
2012壬辰年

これにより、ロケールとカレンダーを両方の format で混在させることも可能になります。

js
let df = new Intl.DateTimeFormat("en-u-ca-chinese", { year: "numeric" });
let date = Date.UTC(2012, 11, 17, 3, 0, 42);
df.format(date);

// 返値
2012(ren - chen);

および formatToParts の場合

js
let opts = { month: "numeric", day: "numeric", year: "numeric" };
let df = new Intl.DateTimeFormat("en-u-ca-chinese", opts);
let date = Date.UTC(2012, 11, 17, 3);
df.formatToParts(date)[
  // 返値
  ({ type: "month", value: "11" },
  { type: "literal", value: "/" },
  { type: "day", value: "4" },
  { type: "literal", value: "/" },
  { type: "relatedYear", value: "2012" })
];

仕様書

Specification
ECMAScript Internationalization API Specification
# sec-Intl.DateTimeFormat.prototype.formatToParts

ブラウザーの互換性

BCD tables only load in the browser

関連情報