Intl.DateTimeFormat API
外部ライブラリなしであらゆるロケールの日付と時刻をフォーマット
はじめに
日付の表示は世界各地で異なります。2024年1月15日はアメリカでは1/15/2024、イギリスでは15/1/2024、日本では2024/1/15と表示されます。時刻形式も異なります。アメリカ人は午前・午後を使用する12時間制を使用しますが、世界の大部分は24時間制を使用しています。
異なるロケールに対応する日付フォーマットのロジックを手動で構築することは複雑でエラーが発生しやすいです。日付と月の順序、区切り文字、時刻形式、タイムゾーン変換、非グレゴリオ暦などの特殊なケースを処理する必要があります。
Intl.DateTimeFormat APIはこの問題を解決します。すべての最新ブラウザで、ロケールを考慮した日付と時刻のフォーマットを組み込みで提供します。外部ライブラリは必要ありません。
基本的な使用方法
日付をフォーマットする最も簡単な方法は、Intl.DateTimeFormatインスタンスを作成し、そのformat()メソッドを呼び出すことです。
const date = new Date(2024, 0, 15, 14, 30);
const formatter = new Intl.DateTimeFormat("en-US");
formatter.format(date);
// "1/15/2024"
ロケールを変更すると、異なるフォーマット規則が適用されます。
const ukFormatter = new Intl.DateTimeFormat("en-GB");
ukFormatter.format(date);
// "15/01/2024"
const japanFormatter = new Intl.DateTimeFormat("ja-JP");
japanFormatter.format(date);
// "2024/1/15"
同じ日付が、地域の慣習に基づいて3つの異なる方法でフォーマットされています。
ロケールについて理解する
ロケールは、言語と地域の設定を識別する文字列です。フォーマットはBCP 47標準に従っています:言語コードの後に、オプションで地域コードが続きます。
一般的なロケールパターン:
"en" // 英語(一般)
"en-US" // 英語(アメリカ合衆国)
"en-GB" // 英語(イギリス)
"es" // スペイン語(一般)
"es-MX" // スペイン語(メキシコ)
"es-ES" // スペイン語(スペイン)
"zh-CN" // 中国語(中国、簡体字)
"zh-TW" // 中国語(台湾、繁体字)
ロケールパラメータを省略すると、ブラウザはユーザーのデフォルトロケールを使用します。
const formatter = new Intl.DateTimeFormat();
formatter.format(date);
// 出力はユーザーのブラウザロケールに基づいて異なります
ロケールの配列を提供することもできます。ブラウザは最初にサポートされているロケールを使用します。
const formatter = new Intl.DateTimeFormat(["es-MX", "es", "en"]);
// 利用可能であればスペイン語(メキシコ)を使用し、一般的なスペイン語、次に英語にフォールバックします
フォーマットオプションの概要
Intl.DateTimeFormat コンストラクターは、フォーマット出力に表示される内容を制御するオプションオブジェクトを受け取ります。フォーマットには2つのアプローチがあります。
最初のアプローチはスタイルショートカットを使用します。これらは迅速で一般的なフォーマットを提供します。
const formatter = new Intl.DateTimeFormat("en-US", {
dateStyle: "full",
timeStyle: "short"
});
formatter.format(date);
// "Monday, January 15, 2024 at 2:30 PM"
2番目のアプローチはコンポーネントオプションを使用します。これにより日付の各部分を細かく制御できます。
const formatter = new Intl.DateTimeFormat("en-US", {
year: "numeric",
month: "long",
day: "numeric",
hour: "numeric",
minute: "numeric"
});
formatter.format(date);
// "January 15, 2024 at 2:30 PM"
スタイルショートカットとコンポーネントオプションを混在させることはできません。フォーマッターごとに一つのアプローチを選択してください。
スタイルショートカット
dateStyle と timeStyle オプションは4つのプリセットフォーマットレベルを提供します。
dateStyle オプションは日付部分をフォーマットします。
const date = new Date(2024, 0, 15);
const full = new Intl.DateTimeFormat("en-US", { dateStyle: "full" });
full.format(date);
// "Monday, January 15, 2024"
const long = new Intl.DateTimeFormat("en-US", { dateStyle: "long" });
long.format(date);
// "January 15, 2024"
const medium = new Intl.DateTimeFormat("en-US", { dateStyle: "medium" });
medium.format(date);
// "Jan 15, 2024"
const short = new Intl.DateTimeFormat("en-US", { dateStyle: "short" });
short.format(date);
// "1/15/24"
timeStyle オプションは時間部分をフォーマットします。
const date = new Date(2024, 0, 15, 14, 30, 45);
const full = new Intl.DateTimeFormat("en-US", { timeStyle: "full" });
full.format(date);
// "2:30:45 PM Eastern Standard Time"
const long = new Intl.DateTimeFormat("en-US", { timeStyle: "long" });
long.format(date);
// "2:30:45 PM EST"
const medium = new Intl.DateTimeFormat("en-US", { timeStyle: "medium" });
medium.format(date);
// "2:30:45 PM"
const short = new Intl.DateTimeFormat("en-US", { timeStyle: "short" });
short.format(date);
// "2:30 PM"
両方のオプションを組み合わせて日付と時間を一緒にフォーマットできます。
const formatter = new Intl.DateTimeFormat("en-US", {
dateStyle: "medium",
timeStyle: "short"
});
formatter.format(date);
// "Jan 15, 2024, 2:30 PM"
スタイルショートカットはロケールの慣習に自動的に適応します。
const usFormatter = new Intl.DateTimeFormat("en-US", {
dateStyle: "short",
timeStyle: "short"
});
usFormatter.format(date);
// "1/15/24, 2:30 PM"
const deFormatter = new Intl.DateTimeFormat("de-DE", {
dateStyle: "short",
timeStyle: "short"
});
deFormatter.format(date);
// "15.1.24, 14:30"
ドイツ語フォーマットではドットを区切り文字として使用し、日と月の順序を逆にし、24時間表示を使用します。アメリカ式フォーマットではスラッシュを使用し、月を先に表示し、AM/PM付きの12時間表示を使用します。同じオプションでもロケールに基づいて異なる出力になります。
コンポーネントオプション
コンポーネントオプションは表示内容と方法を正確に制御します。各オプションは日付や時刻の一部を指定します。
yearオプションは年を表示します。
const formatter = new Intl.DateTimeFormat("en-US", { year: "numeric" });
formatter.format(date);
// "2024"
const twoDigit = new Intl.DateTimeFormat("en-US", { year: "2-digit" });
twoDigit.format(date);
// "24"
monthオプションは月をさまざまな形式で表示します。
const numeric = new Intl.DateTimeFormat("en-US", { month: "numeric" });
numeric.format(date);
// "1"
const twoDigit = new Intl.DateTimeFormat("en-US", { month: "2-digit" });
twoDigit.format(date);
// "01"
const long = new Intl.DateTimeFormat("en-US", { month: "long" });
long.format(date);
// "January"
const short = new Intl.DateTimeFormat("en-US", { month: "short" });
short.format(date);
// "Jan"
const narrow = new Intl.DateTimeFormat("en-US", { month: "narrow" });
narrow.format(date);
// "J"
dayオプションは月の日を表示します。
const formatter = new Intl.DateTimeFormat("en-US", { day: "numeric" });
formatter.format(date);
// "15"
const twoDigit = new Intl.DateTimeFormat("en-US", { day: "2-digit" });
twoDigit.format(date);
// "15"
weekdayオプションは曜日を表示します。
const long = new Intl.DateTimeFormat("en-US", { weekday: "long" });
long.format(date);
// "Monday"
const short = new Intl.DateTimeFormat("en-US", { weekday: "short" });
short.format(date);
// "Mon"
const narrow = new Intl.DateTimeFormat("en-US", { weekday: "narrow" });
narrow.format(date);
// "M"
複数のコンポーネントオプションを組み合わせてカスタム日付形式を構築できます。
const formatter = new Intl.DateTimeFormat("en-US", {
weekday: "long",
year: "numeric",
month: "long",
day: "numeric"
});
formatter.format(date);
// "Monday, January 15, 2024"
ブラウザはロケールの規則に基づいて間隔や句読点を処理します。
時刻フォーマット
時間コンポーネントのオプションは、時、分、秒の表示を制御します。
const date = new Date(2024, 0, 15, 14, 30, 45);
const formatter = new Intl.DateTimeFormat("en-US", {
hour: "numeric",
minute: "numeric",
second: "numeric"
});
formatter.format(date);
// "2:30:45 PM"
hour12オプションは12時間表示と24時間表示を制御します。
const hour12 = new Intl.DateTimeFormat("en-US", {
hour: "numeric",
minute: "numeric",
hour12: true
});
hour12.format(date);
// "2:30 PM"
const hour24 = new Intl.DateTimeFormat("en-US", {
hour: "numeric",
minute: "numeric",
hour12: false
});
hour24.format(date);
// "14:30"
hourCycleオプションは時間表示をより細かく制御します。4つのオプションがあります。
// h11: 0-11
const h11 = new Intl.DateTimeFormat("en-US", {
hour: "numeric",
hourCycle: "h11"
});
h11.format(new Date(2024, 0, 15, 0, 30));
// "0:30 AM"
// h12: 1-12
const h12 = new Intl.DateTimeFormat("en-US", {
hour: "numeric",
hourCycle: "h12"
});
h12.format(new Date(2024, 0, 15, 0, 30));
// "12:30 AM"
// h23: 0-23
const h23 = new Intl.DateTimeFormat("en-US", {
hour: "numeric",
hourCycle: "h23"
});
h23.format(new Date(2024, 0, 15, 0, 30));
// "0:30"
// h24: 1-24
const h24 = new Intl.DateTimeFormat("en-US", {
hour: "numeric",
hourCycle: "h24"
});
h24.format(new Date(2024, 0, 15, 0, 30));
// "24:30"
この違いは真夜中に重要です。h11サイクルでは0を使用し、h12では12を使用します。同様に、h23では0を使用し、h24では24を使用します。
dayPeriodオプションは12時間表示に説明的な時間帯マーカーを追加します。
const morning = new Date(2024, 0, 15, 10, 30);
const afternoon = new Date(2024, 0, 15, 14, 30);
const night = new Date(2024, 0, 15, 22, 30);
const formatter = new Intl.DateTimeFormat("en-US", {
hour: "numeric",
minute: "numeric",
dayPeriod: "long"
});
formatter.format(morning);
// "10:30 in the morning"
formatter.format(afternoon);
// "2:30 in the afternoon"
formatter.format(night);
// "10:30 at night"
dayPeriodオプションは12時間表示形式でのみ機能します。
fractionalSecondDigitsオプションは秒未満の精度を表示します。
const date = new Date(2024, 0, 15, 14, 30, 45, 123);
const oneDigit = new Intl.DateTimeFormat("en-US", {
hour: "numeric",
minute: "numeric",
second: "numeric",
fractionalSecondDigits: 1
});
oneDigit.format(date);
// "2:30:45.1 PM"
const threeDigits = new Intl.DateTimeFormat("en-US", {
hour: "numeric",
minute: "numeric",
second: "numeric",
fractionalSecondDigits: 3
});
threeDigits.format(date);
// "2:30:45.123 PM"
1桁、2桁、または3桁の小数部分を指定できます。
タイムゾーンの処理
timeZoneオプションは日付を特定のタイムゾーンに変換します。
const date = new Date("2024-01-15T14:30:00Z"); // UTC時間
const newYork = new Intl.DateTimeFormat("en-US", {
timeZone: "America/New_York",
dateStyle: "full",
timeStyle: "long"
});
newYork.format(date);
// "Monday, January 15, 2024 at 9:30:00 AM EST"
const tokyo = new Intl.DateTimeFormat("ja-JP", {
timeZone: "Asia/Tokyo",
dateStyle: "full",
timeStyle: "long"
});
tokyo.format(date);
// "2024年1月15日月曜日 23:30:00 日本標準時"
const london = new Intl.DateTimeFormat("en-GB", {
timeZone: "Europe/London",
dateStyle: "full",
timeStyle: "long"
});
london.format(date);
// "Monday, 15 January 2024 at 14:30:00 GMT"
同じ時間でもタイムゾーンに基づいて表示が異なります。America/New_York、Europe/London、Asia/TokyoなどのIANAタイムゾーン識別子を使用してください。
timeZoneNameオプションはタイムゾーン名を表示します。
const formatter = new Intl.DateTimeFormat("en-US", {
hour: "numeric",
minute: "numeric",
timeZone: "America/New_York",
timeZoneName: "short"
});
formatter.format(date);
// "9:30 AM EST"
const long = new Intl.DateTimeFormat("en-US", {
hour: "numeric",
minute: "numeric",
timeZone: "America/New_York",
timeZoneName: "long"
});
long.format(date);
// "9:30 AM Eastern Standard Time"
const shortOffset = new Intl.DateTimeFormat("en-US", {
hour: "numeric",
minute: "numeric",
timeZone: "America/New_York",
timeZoneName: "shortOffset"
});
shortOffset.format(date);
// "9:30 AM GMT-5"
const longOffset = new Intl.DateTimeFormat("en-US", {
hour: "numeric",
minute: "numeric",
timeZone: "America/New_York",
timeZoneName: "longOffset"
});
longOffset.format(date);
// "9:30 AM GMT-05:00"
異なるtimeZoneName値により、異なるレベルの詳細情報が提供されます。
暦システムと数字体系
calendarオプションは非グレゴリオ暦をサポートしています。
const date = new Date(2024, 0, 15);
const gregorian = new Intl.DateTimeFormat("en-US", {
calendar: "gregory",
year: "numeric",
month: "long",
day: "numeric"
});
gregorian.format(date);
// "January 15, 2024"
const japanese = new Intl.DateTimeFormat("ja-JP", {
calendar: "japanese",
year: "numeric",
month: "long",
day: "numeric"
});
japanese.format(date);
// "令和6年1月15日"
const islamic = new Intl.DateTimeFormat("ar-SA", {
calendar: "islamic",
year: "numeric",
month: "long",
day: "numeric"
});
islamic.format(date);
// "٦ رجب ١٤٤٥"
const chinese = new Intl.DateTimeFormat("zh-CN", {
calendar: "chinese",
year: "numeric",
month: "long",
day: "numeric"
});
chinese.format(date);
// "2023甲辰年腊月初五"
同じ日付が異なる暦システムに変換されます。利用可能な暦にはgregory、japanese、islamic、islamic-umalqura、islamic-tbla、islamic-civil、islamic-rgsa、chinese、hebrew、indian、persianなどがあります。
numberingSystemオプションは異なる文字体系で数字を表示します。
const date = new Date(2024, 0, 15);
const western = new Intl.DateTimeFormat("en-US", {
numberingSystem: "latn",
year: "numeric",
month: "numeric",
day: "numeric"
});
western.format(date);
// "1/15/2024"
const arabic = new Intl.DateTimeFormat("en-US", {
numberingSystem: "arab",
year: "numeric",
month: "numeric",
day: "numeric"
});
arabic.format(date);
// "١/١٥/٢٠٢٤"
const devanagari = new Intl.DateTimeFormat("en-US", {
numberingSystem: "deva",
year: "numeric",
month: "numeric",
day: "numeric"
});
devanagari.format(date);
// "१/१५/२०२४"
const bengali = new Intl.DateTimeFormat("en-US", {
numberingSystem: "beng",
year: "numeric",
month: "numeric",
day: "numeric"
});
bengali.format(date);
// "১/১৫/২০২৪"
利用可能な数字体系にはlatn(欧米数字)、arab(アラビア・インド数字)、arabext(拡張アラビア・インド数字)、beng(ベンガル数字)、deva(デーヴァナーガリー数字)など多数あります。
日付範囲のフォーマット
formatRange()メソッドは、重複する情報を賢く省略して日付範囲をフォーマットします。
const start = new Date(2024, 0, 15);
const end = new Date(2024, 0, 20);
const formatter = new Intl.DateTimeFormat("en-US", {
year: "numeric",
month: "long",
day: "numeric"
});
formatter.formatRange(start, end);
// "January 15 – 20, 2024"
フォーマッタは繰り返し情報を省略します。両方の日付が2024年1月なので、出力には月と年が一度だけ含まれます。
範囲が異なる月にまたがる場合、両方が表示されます。
const start = new Date(2024, 0, 15);
const end = new Date(2024, 1, 20);
formatter.formatRange(start, end);
// "January 15 – February 20, 2024"
範囲が異なる年にまたがる場合、すべての情報が表示されます。
const start = new Date(2024, 0, 15);
const end = new Date(2025, 1, 20);
formatter.formatRange(start, end);
// "January 15, 2024 – February 20, 2025"
formatRange()メソッドは時間範囲でも機能します。
const start = new Date(2024, 0, 15, 14, 30);
const end = new Date(2024, 0, 15, 16, 45);
const formatter = new Intl.DateTimeFormat("en-US", {
month: "long",
day: "numeric",
hour: "numeric",
minute: "numeric"
});
formatter.formatRange(start, end);
// "January 15, 2:30 – 4:45 PM"
両方の時間が同じ日に発生するため、日付は一度だけ表示されます。
フォーマットされた部分へのアクセス
formatToParts()メソッドは、フォーマットされた日付の各部分を表すオブジェクトの配列を返します。これによりカスタムフォーマットロジックが可能になります。
const date = new Date(2024, 0, 15, 14, 30);
const formatter = new Intl.DateTimeFormat("en-US", {
year: "numeric",
month: "long",
day: "numeric",
hour: "numeric",
minute: "numeric"
});
const parts = formatter.formatToParts(date);
配列内の各オブジェクトにはtypeとvalueプロパティがあります。
[
{ type: "month", value: "January" },
{ type: "literal", value: " " },
{ type: "day", value: "15" },
{ type: "literal", value: ", " },
{ type: "year", value: "2024" },
{ type: "literal", value: " at " },
{ type: "hour", value: "2" },
{ type: "literal", value: ":" },
{ type: "minute", value: "30" },
{ type: "literal", value: " " },
{ type: "dayPeriod", value: "PM" }
]
これらの部分をフィルタリングして操作し、カスタムフォーマットを構築できます。
const dateParts = parts.filter(part =>
["month", "day", "year"].includes(part.type)
);
const dateString = dateParts.map(part => part.value).join("/");
// "January/15/2024"
formatRangeToParts()メソッドは日付範囲に対して同様の機能を提供します。
const start = new Date(2024, 0, 15);
const end = new Date(2024, 0, 20);
const formatter = new Intl.DateTimeFormat("en-US", {
year: "numeric",
month: "long",
day: "numeric"
});
const parts = formatter.formatRangeToParts(start, end);
各部分オブジェクトには、開始日または終了日のどちらから来たかを示すsourceプロパティが含まれています。
[
{ type: "month", value: "January", source: "startRange" },
{ type: "literal", value: " ", source: "startRange" },
{ type: "day", value: "15", source: "startRange" },
{ type: "literal", value: " – ", source: "shared" },
{ type: "day", value: "20", source: "endRange" },
{ type: "literal", value: ", ", source: "shared" },
{ type: "year", value: "2024", source: "shared" }
]
ベストプラクティス
同じオプションで複数の日付をフォーマットする場合は、フォーマッターインスタンスを再利用してください。フォーマッターの作成にはロケールのネゴシエーションとオプションの解決が含まれ、わずかなパフォーマンスコストがかかります。
// 効率が悪い方法
dates.forEach(date => {
const formatted = new Intl.DateTimeFormat("en-US").format(date);
console.log(formatted);
});
// より効率的な方法
const formatter = new Intl.DateTimeFormat("en-US");
dates.forEach(date => {
const formatted = formatter.format(date);
console.log(formatted);
});
可能な限り、ロケールパラメータを省略してユーザーのブラウザロケールを使用してください。これによりユーザーの設定が尊重されます。
const formatter = new Intl.DateTimeFormat();
// ブラウザのロケールを自動的に使用
特定の地域をターゲットにする場合は、フォールバックロケールを提供してください。優先ロケールが利用できない場合、ブラウザは次のオプションを使用します。
const formatter = new Intl.DateTimeFormat(["fr-CA", "fr", "en"]);
// フランス語(カナダ)を優先し、フランス語、英語の順にフォールバック
一般的な日付と時刻の表示にはスタイルショートカットを使用してください。これらはロケールの慣習に自動的に適応し、設定が少なくて済みます。
const formatter = new Intl.DateTimeFormat("en-US", {
dateStyle: "medium",
timeStyle: "short"
});
出力形式を正確に制御する必要がある場合は、コンポーネントオプションを使用してください。
const formatter = new Intl.DateTimeFormat("en-US", {
weekday: "long",
year: "numeric",
month: "long",
day: "numeric"
});
リモートユーザー向けや予定されたイベントの時刻を表示する場合は、常にタイムゾーンを指定してください。タイムゾーンを指定しないと、日付はユーザーのローカルタイムゾーンでフォーマットされ、意図と一致しない場合があります。
const formatter = new Intl.DateTimeFormat("en-US", {
timeZone: "America/New_York",
dateStyle: "full",
timeStyle: "long"
});
日付範囲には、各日付を個別にフォーマットして連結するのではなく、formatRange()を使用してください。このメソッドは冗長な情報を賢く省略します。
// わかりにくい方法
const startFormatted = formatter.format(start);
const endFormatted = formatter.format(end);
const range = `${startFormatted} to ${endFormatted}`;
// より良い方法
const range = formatter.formatRange(start, end);
dayPeriod、fractionalSecondDigits、特定のtimeZoneName値などの高度な機能については、ブラウザの互換性を確認してください。すべての最新ブラウザは基本機能をサポートしていますが、新しいオプションでは古いブラウザ向けのフォールバックが必要な場合があります。