ユーザーのロケールで時刻を書式設定する方法
JavaScriptを使用して、各ユーザーの地域規則に従って時刻を表示する
はじめに
時刻は世界中で異なる表示形式を持ちます。アメリカ人は通常、午後3時30分を3:30 PMと表示しますが、ヨーロッパのほとんどの地域では15:30と表示されることを期待します。時刻形式をハードコーディングすると、すべてのユーザーが同じ規則に従うと仮定することになります。
馴染みのない形式で時刻を表示すると、混乱が生じます。24時間表記に慣れたユーザーが3:30 PMを見ると、それが午前か午後かを理解するために頭の中で変換する必要があります。この認知的負荷は、アプリケーション内のすべての時刻表示で積み重なります。
JavaScriptは、時刻の書式設定を自動的に処理するIntl.DateTimeFormat APIを提供しています。このレッスンでは、時刻形式が文化によって異なる理由、APIの仕組み、そしてあらゆるロケールで時刻を正しく書式設定する方法について説明します。
時刻形式がロケールによって異なる理由
異なる地域では、時刻を表示するための異なる規則が発展してきました。これらの規則は、歴史的慣習、教育システム、文化的嗜好を反映しています。普遍的な単一の形式は存在しません。
アメリカ、カナダ、オーストラリア、フィリピンでは、時刻はAMとPMの表示を伴う12時間形式を使用します。午後3時30分は3:30 PMと表示されます。
ヨーロッパのほとんどの国、ラテンアメリカ、アジアでは、時刻はAMやPMの表示なしで24時間形式を使用します。同じ時刻は15:30と表示されます。
時と分の間の区切り文字も異なります。英語圏の国ではコロンを使用しますが、一部のロケールではピリオドやその他の句読点を使用します。
AMとPMの表示方法も異なります。英語ではAMとPMを使用し、スペイン語ではa.m.とp.m.を使用し、一部のロケールではこれらの表示を時刻の後ではなく前に配置します。
時刻を表示する際は、時刻形式と特定の書式規則の両方について、ユーザーの期待に合わせる必要があります。
Intl.DateTimeFormatを使用した時刻の書式設定
Intl.DateTimeFormatコンストラクタは、ロケール固有の規則を適用するフォーマッタを作成します。時刻を書式設定するには、最初の引数としてロケール識別子を渡し、2番目の引数で時刻関連のオプションを指定します。
const formatter = new Intl.DateTimeFormat('en-US', {
hour: 'numeric',
minute: 'numeric'
});
const date = new Date('2025-03-15T15:30:00');
console.log(formatter.format(date));
// Output: "3:30 PM"
これにより、時と分を表示する米国英語用のフォーマッタが作成されます。hourおよびminuteオプションは、これらのコンポーネントを含めるようフォーマッタに指示します。format()メソッドは、Dateオブジェクトを適切な書式の文字列に変換します。
Dateコンストラクタは、2025-03-15T15:30:00のようなISO 8601日時文字列を受け入れます。これにより、2025年3月15日午後3時30分を表すDateオブジェクトが作成されます。その後、フォーマッタはこれをロケール固有の時刻文字列に変換します。
異なるロケールでの同じ時刻の書式設定
コンストラクタに渡すロケール識別子を変更することで、異なるロケールで同じ時刻を書式設定できます。
const date = new Date('2025-03-15T15:30:00');
const usFormatter = new Intl.DateTimeFormat('en-US', {
hour: 'numeric',
minute: 'numeric'
});
console.log(usFormatter.format(date));
// Output: "3:30 PM"
const gbFormatter = new Intl.DateTimeFormat('en-GB', {
hour: 'numeric',
minute: 'numeric'
});
console.log(gbFormatter.format(date));
// Output: "15:30"
const deFormatter = new Intl.DateTimeFormat('de-DE', {
hour: 'numeric',
minute: 'numeric'
});
console.log(deFormatter.format(date));
// Output: "15:30"
const frFormatter = new Intl.DateTimeFormat('fr-FR', {
hour: 'numeric',
minute: 'numeric'
});
console.log(frFormatter.format(date));
// Output: "15:30"
各フォーマッタは異なる規則を適用します。米国のフォーマッタはAM/PM付きの12時間形式を使用します。英国、ドイツ、フランスのフォーマッタはすべて、AM/PM表示なしの24時間形式を使用します。
各ロケールがどの形式を使用するかを知る必要はありません。APIはロケール識別子に基づいて、これらの詳細を自動的に処理します。
時刻表示への秒の追加
secondオプションを追加して、時と分とともに秒を表示できます。
const formatter = new Intl.DateTimeFormat('en-US', {
hour: 'numeric',
minute: 'numeric',
second: 'numeric'
});
const date = new Date('2025-03-15T15:30:45');
console.log(formatter.format(date));
// Output: "3:30:45 PM"
secondオプションは、hourおよびminuteと同じように機能します。出力に秒を含めるには、'numeric'に設定します。
2桁での桁埋めの制御
hour、minute、secondオプションは2つの値を受け付けます。'numeric'と'2-digit'です。'numeric'値は桁埋めなしで数字を表示し、'2-digit'は常に先頭にゼロを付けて2桁で表示します。
const date = new Date('2025-03-15T09:05:03');
const numericFormatter = new Intl.DateTimeFormat('en-US', {
hour: 'numeric',
minute: 'numeric',
second: 'numeric'
});
console.log(numericFormatter.format(date));
// Output: "9:05:03 AM"
const twoDigitFormatter = new Intl.DateTimeFormat('en-US', {
hour: '2-digit',
minute: '2-digit',
second: '2-digit'
});
console.log(twoDigitFormatter.format(date));
// Output: "09:05:03 AM"
数値フォーマッタは9:05:03 AMを時の部分に1桁で表示します。2桁フォーマッタは09:05:03 AMを時の部分に先頭ゼロ付きで表示します。分と秒は設定に関係なく通常は桁埋めされるため、両方とも2桁で表示されます。
12時間形式または24時間形式の強制
デフォルトでは、APIはロケールで優先される時刻形式を使用します。hour12オプションでこれを上書きできます。
const date = new Date('2025-03-15T15:30:00');
const hour12Formatter = new Intl.DateTimeFormat('en-GB', {
hour: 'numeric',
minute: 'numeric',
hour12: true
});
console.log(hour12Formatter.format(date));
// Output: "3:30 pm"
const hour24Formatter = new Intl.DateTimeFormat('en-US', {
hour: 'numeric',
minute: 'numeric',
hour12: false
});
console.log(hour24Formatter.format(date));
// Output: "15:30"
hour12: trueを設定すると、通常24時間形式を使用するロケールでも12時間形式が強制されます。hour12: falseを設定すると、通常12時間形式を使用するロケールでも24時間形式が強制されます。
ロケールは句読点や空白などの他のフォーマット詳細を引き続き決定します。hour12: trueを使用した英国フォーマッタは3:30 pmを小文字のpmで表示しますが、米国フォーマッタは3:30 PMを大文字のPMで表示します。
ユーザーのロケールに合わせた時刻のフォーマット
特定のロケールをハードコーディングする代わりに、ブラウザからユーザーの優先言語を使用できます。navigator.languageプロパティは、ユーザーの最優先言語設定を返します。
const userLocale = navigator.language;
const formatter = new Intl.DateTimeFormat(userLocale, {
hour: 'numeric',
minute: 'numeric'
});
const date = new Date('2025-03-15T15:30:00');
console.log(formatter.format(date));
// Output varies by user's locale
// For en-US: "3:30 PM"
// For en-GB: "15:30"
// For de-DE: "15:30"
// For fr-FR: "15:30"
このアプローチでは、ユーザーが手動でロケールを選択する必要なく、各ユーザーの期待に応じて時刻が表示されます。ブラウザが言語設定を提供し、Intl APIが適切なフォーマット規則を適用します。
優先言語の配列全体を渡して、フォールバック動作を有効にすることもできます。
const formatter = new Intl.DateTimeFormat(navigator.languages, {
hour: 'numeric',
minute: 'numeric'
});
const date = new Date('2025-03-15T15:30:00');
console.log(formatter.format(date));
APIは配列からサポートする最初のロケールを使用します。これにより、ユーザーの第一希望が利用できない場合に、より適切なフォールバック処理が提供されます。
フォーマットする時刻の作成
時刻情報を含むDateオブジェクトは、いくつかの方法で作成できます。最も信頼性の高いアプローチは、ISO 8601日時文字列を使用することです。
const time1 = new Date('2025-03-15T09:00:00');
const time2 = new Date('2025-03-15T15:30:00');
const time3 = new Date('2025-03-15T23:45:30');
const formatter = new Intl.DateTimeFormat('en-US', {
hour: 'numeric',
minute: 'numeric'
});
console.log(formatter.format(time1));
// Output: "9:00 AM"
console.log(formatter.format(time2));
// Output: "3:30 PM"
console.log(formatter.format(time3));
// Output: "11:45 PM"
ISO 8601日時文字列はYYYY-MM-DDTHH:MM:SS形式を使用します。Tは日付と時刻を区切ります。この形式は曖昧さがなく、すべてのロケールとタイムゾーンで一貫して機能します。
タイムスタンプからの時刻のフォーマット
UnixタイムスタンプからもDateオブジェクトを作成できます。Unixタイムスタンプは、1970年1月1日UTCからのミリ秒数を表します。
const timestamp = 1710515400000; // March 15, 2025 at 3:30 PM
const date = new Date(timestamp);
const formatter = new Intl.DateTimeFormat('en-US', {
hour: 'numeric',
minute: 'numeric'
});
console.log(formatter.format(date));
// Output: "3:30 PM"
このアプローチは、API、データベース、または時刻を数値として表す他のシステムからタイムスタンプを受け取る場合に機能します。
また、最初にDateオブジェクトを作成せずに、タイムスタンプを直接format()メソッドに渡すこともできます。
const formatter = new Intl.DateTimeFormat('en-US', {
hour: 'numeric',
minute: 'numeric'
});
const timestamp = 1710515400000;
console.log(formatter.format(timestamp));
// Output: "3:30 PM"
APIはDateオブジェクトとタイムスタンプの両方を受け入れます。コードに適したアプローチを使用してください。
現在時刻のフォーマット
現在時刻をフォーマットするには、引数なしでDateオブジェクトを作成します。これにより、現在の瞬間を表すDateオブジェクトが作成されます。
const formatter = new Intl.DateTimeFormat('en-US', {
hour: 'numeric',
minute: 'numeric',
second: 'numeric'
});
const now = new Date();
console.log(formatter.format(now));
// Output: "3:45:12 PM" (or current time when run)
また、Date.now()を直接渡すこともできます。これは現在のタイムスタンプを数値として返します。
const formatter = new Intl.DateTimeFormat('en-US', {
hour: 'numeric',
minute: 'numeric',
second: 'numeric'
});
console.log(formatter.format(Date.now()));
// Output: "3:45:12 PM" (or current time when run)
どちらのアプローチも同一の結果を生成します。
パフォーマンスのためのフォーマッターの再利用
新しいIntl.DateTimeFormatインスタンスの作成には、ロケールデータの読み込みとオプションの処理が含まれます。同じロケールと設定で複数回フォーマットする必要がある場合は、フォーマッターを一度作成して再利用してください。
const formatter = new Intl.DateTimeFormat('en-US', {
hour: 'numeric',
minute: 'numeric'
});
const times = [
new Date('2025-03-15T09:00:00'),
new Date('2025-03-15T12:30:00'),
new Date('2025-03-15T18:45:00')
];
times.forEach(time => {
console.log(formatter.format(time));
});
// Output:
// "9:00 AM"
// "12:30 PM"
// "6:45 PM"
このアプローチは、毎回新しいフォーマッターを作成するよりも効率的です。数百または数千の時刻値を含む配列をフォーマットする場合、パフォーマンスの差が顕著になります。
テンプレートでの時刻のフォーマット
Intl.DateTimeFormatは、ユーザーに時刻を表示する任意の場所で使用できます。これには、HTMLテンプレートへのフォーマット済み時刻の挿入、テーブルでの時刻の表示、またはユーザーインターフェースでのタイムスタンプの表示が含まれます。
const formatter = new Intl.DateTimeFormat(navigator.language, {
hour: 'numeric',
minute: 'numeric'
});
const eventStart = new Date('2025-03-15T14:00:00');
const eventEnd = new Date('2025-03-15T16:30:00');
document.getElementById('start-time').textContent = formatter.format(eventStart);
document.getElementById('end-time').textContent = formatter.format(eventEnd);
フォーマットされた文字列は、他の文字列値と同様に機能します。テキストコンテンツ、属性、またはユーザーに情報を表示するその他のコンテキストに挿入できます。