AM/PMやロケール固有の日中区分の表示方法

JavaScriptを使って、文化ごとの時間帯の区分方法に合わせた時刻表示を行う

はじめに

たとえば「4:00」とだけ表示しても、それが朝なのか午後なのか、ユーザーには分かりません。英語では文脈を明確にするためにAMやPMを付け足します。4:00 AMは日の出前、4:00 PMは午後の時間帯を指します。

他の言語では、単にAMやPMを訳すのではありません。多くの文化圏では一日を2つ以上の時間帯に区切り、早朝・朝・午後・夕方・夜など細かい呼び方が存在します。例えばスペイン語には深夜から夜明け前を指す「madrugada」があり、ドイツ語では一日を2区分ではなく6区分に分けています。また、ある言語では1:00 AMのことを「夜の1時」と呼ぶ場合もあります。

JavaScriptのIntl.DateTimeFormatには、これら文化ごとの時間帯を自動で表示するdayPeriodオプションがあります。このレッスンでは、文化ごとに異なる日中区分の仕組みや、国際アプリケーションでなぜ重要なのか、そして適切な時間帯ラベルの付け方を解説します。

文化ごとに異なる日中区分

各文化には、それぞれ24時間を名前付きの区分に分ける方法があり、この分け方はその文化圏の人々の時間に対する捉え方や表現の仕方に根ざしています。

英語圏では一日を4つに区切ります。モーニングは真夜中から正午まで、アフタヌーンは正午から夕方まで、イブニングは夕方から日没まで、ナイトは日没から真夜中までを指します。AMとPMによる表記は、12時間制における簡易的な2区分方式です。

スペイン語では、深夜から人々が起きる前までを「madrugada」とし、これによって夜遅くの時間帯と早朝を区別する5つの区分が存在します。

ロシア語話者は、人々が通常眠っている時間帯を「ночь」(夜)と呼びます。例えば、午前1時は「朝の1時」ではなく「夜の1時」と表現されます。これは、その時間帯には通常寝ているためです。

ドイツ語では1日を6つの時間帯に分けています。「Morgen」(朝)、「Vormittag」(午前)、「Mittag」(正午)、「Nachmittag」(午後)、「Abend」(夕方)、「Nacht」(夜)のそれぞれが特定の時間帯を指します。

インドネシア語では、日中を太陽の位置によって4つの時間帯に分けています。「pagi」(夜明けから午前10時まで)、「siang」(午前10時から午後2時まで)、「sore」(午後2時から日没まで)、「malam」(夜)です。

ベンガル語では1日を6つの時間帯に分けています。「ভোর」(夜明け)、「সকাল」(朝)、「দুপুর」(昼過ぎ)、「বিকাল」(夕方)、「সন্ধ্যা」(夕暮れ)、「রাত」(夜)と、それぞれが決まった時間を示します。

国際的なアプリケーションで時刻を表示する場合、各文化圏の人が普段どう時間を表現しているかに合った用語を使うことが重要です。すべてのユーザーに「4 AM」とだけ表示するのでは、多言語がその時間をどう表現するかを考慮していません。

dayPeriod オプションについて理解する

dayPeriod オプションは、日付と時刻をフォーマットする際にロケール固有の時間帯表現(午前・午後など)を含めるようにフォーマッターへ指示します。単に時・分だけを表示するのではなく、対象言語に適した時間帯名称も付与されます。

このオプションは12時間表記でのみ動作します。24時間表記の場合、時刻そのものが十分な情報となるためです。たとえば04:00は明らかに朝、16:00は明らかに午後なので追加ラベルは不要です。12時間表記では同じ時刻が繰り返されるため、時間帯表現で区別する必要があります。

dayPeriod オプションには3つの値が指定できます。narrow は最も短い形、通常は1文字や略語で表現されます。short は省略形、long は完全な単語またはフレーズを出力します。

多くのロケールでは、これら3つの値は同じ出力結果となります。Unicode のロケールデータは、すべてのロケールとフォーマット長の組み合わせごとに異なる形式を定義しているわけではありません。異なる形式が存在しない場合、どの値を指定しても結果は同じになります。

時間の昼夜区分(Day period)のフォーマット

昼夜区分を表示するには、Intl.DateTimeFormat インスタンスを作成し、dayPeriod オプションに narrowshort、または long を設定します。また、hour などの時刻コンポーネントオプションを追加し、hourCycle で12時間表記を指定してください。

const date = new Date('2025-01-15T04:30:00');

const formatter = new Intl.DateTimeFormat('en-US', {
  hour: 'numeric',
  minute: 'numeric',
  hourCycle: 'h12',
  dayPeriod: 'long'
});

console.log(formatter.format(date));
// Output: "4:30 in the morning"

これにより、時・分・昼夜区分を表示するフォーマッターが作成されます。hourCycle: 'h12' オプションで12時間表記を指定しているため、昼夜区分を正しく表示できます。また、dayPeriod: 'long' オプションで、昼夜区分のフルフレーズを指定しています。

dayPeriod オプションを指定しない場合、フォーマッターは代わりに「4:30 AM」と表示します。昼夜区分オプションを使うことで、単なる AM/PM 表示ではなく、より詳しいフレーズを表示できます。

異なる時刻での昼夜区分の表示

昼夜区分は、フォーマットする時間によって変化します。フォーマッターはロケールの慣習に従い、各時刻に適切な区分を自動的に選択します。

const options = {
  hour: 'numeric',
  minute: 'numeric',
  hourCycle: 'h12',
  dayPeriod: 'long'
};

const formatter = new Intl.DateTimeFormat('en-US', options);

const morning = new Date('2025-01-15T04:30:00');
console.log(formatter.format(morning));
// Output: "4:30 in the morning"

const afternoon = new Date('2025-01-15T14:30:00');
console.log(formatter.format(afternoon));
// Output: "2:30 in the afternoon"

const evening = new Date('2025-01-15T20:30:00');
console.log(formatter.format(evening));
// Output: "8:30 in the evening"

const night = new Date('2025-01-15T23:30:00');
console.log(formatter.format(night));
// Output: "11:30 at night"

英語では朝・午後・夕方・夜を区別します。各時間帯に合ったフレーズが時刻によって自動的に表示されます。どの区分に該当するかを判断する必要はありません。フォーマッターが、Unicode のロケールデータを元に自動で適切に処理します。

ナロー・ショート・ロングフォーマットの比較

一部のロケールでは、これら3種類のフォーマット長で異なる出力が得られます。違いは言語によって様々で、微妙な場合や違いがない場合もあります。

const date = new Date('2025-01-15T04:30:00');

const narrow = new Intl.DateTimeFormat('en-US', {
  hour: 'numeric',
  hourCycle: 'h12',
  dayPeriod: 'narrow'
});
console.log(narrow.format(date));
// Output: "4 in the morning"

const short = new Intl.DateTimeFormat('en-US', {
  hour: 'numeric',
  hourCycle: 'h12',
  dayPeriod: 'short'
});
console.log(short.format(date));
// Output: "4 in the morning"

const long = new Intl.DateTimeFormat('en-US', {
  hour: 'numeric',
  hourCycle: 'h12',
  dayPeriod: 'long'
});
console.log(long.format(date));
// Output: "4 in the morning"

米国英語の場合、いずれのフォーマット長を選んでも出力は同じです。この言語と時刻の組み合わせでは、ロケールデータに違いが登録されていません。

一部のロケールでは、時間表記の長短を区別します。例えばフランス語では、短縮形と長い形式で異なる表現が使われます。

const date = new Date('2025-01-15T04:30:00');

const frNarrow = new Intl.DateTimeFormat('fr-FR', {
  hour: 'numeric',
  hourCycle: 'h12',
  dayPeriod: 'narrow'
});
console.log(frNarrow.format(date));
// Output: "4 mat."

const frLong = new Intl.DateTimeFormat('fr-FR', {
  hour: 'numeric',
  hourCycle: 'h12',
  dayPeriod: 'long'
});
console.log(frLong.format(date));
// Output: "4 du matin"

フランス語では「mat.」が省略形、「du matin」が長い形式として使われます。どちらも「朝」を意味しますが、長い形式の方がより明確に伝わります。

特に短い出力が必要な場合を除いては、分かりやすさのためにlongをご使用ください。長い形式の方がユーザーにとって理解しやすく、多くのロケールでは短縮形が用意されていない場合もあります。

ロケールごとの日中区分のしくみ

ロケールによって日中区分の呼び方や、1日の区切り方が異なります。フォーマッターは各ロケールの慣習を自動で反映します。

const date = new Date('2025-01-15T04:30:00');
const options = {
  hour: 'numeric',
  hourCycle: 'h12',
  dayPeriod: 'long'
};

const enUS = new Intl.DateTimeFormat('en-US', options);
console.log(enUS.format(date));
// Output: "4 in the morning"

const enGB = new Intl.DateTimeFormat('en-GB', options);
console.log(enGB.format(date));
// Output: "4 at night"

const deDK = new Intl.DateTimeFormat('de-DE', options);
console.log(deDK.format(date));
// Output: "4 morgens"

const fr = new Intl.DateTimeFormat('fr-FR', options);
console.log(fr.format(date));
// Output: "4 du matin"

イギリス英語では午前4時30分を「夜」とみなしますが、これは日中区分の文化的な境界の違いを表しています。ドイツ語では「morgens」、フランス語では同じ時間帯に「du matin」が使われます。

これらの違いはミスや矛盾ではなく、時間の捉え方や表現方法にある実際の文化的な違いを反映しています。フォーマッターはロケールに応じて自動的にこれらの違いを尊重します。

日中区分は12時間表記が必要

dayPeriod オプションは、hourCycle: 'h12' または hourCycle: 'h11' を利用して12時間表記を指定した場合のみ有効です。12時間表記でない場合、日中区分は表示されません。

const date = new Date('2025-01-15T04:30:00');

const with12Hour = new Intl.DateTimeFormat('en-US', {
  hour: 'numeric',
  hourCycle: 'h12',
  dayPeriod: 'long'
});
console.log(with12Hour.format(date));
// Output: "4 in the morning"

const with24Hour = new Intl.DateTimeFormat('en-US', {
  hour: 'numeric',
  hourCycle: 'h23',
  dayPeriod: 'long'
});
console.log(with24Hour.format(date));
// Output: "04"

24時間表記では、オプションを指定しても日中区分は表示されません。24時間表記では、時刻自体が十分な情報となるため、追加のラベルは不要です。

h12h11 の違いは、真夜中や正午をどう数字で表すかにあります。標準的な12時間時計(1〜12時)を使う場合は h12 を、0〜11時方式の場合は h11 をご利用ください。どちらも日中区分に対応しています。

午前・午後区分と分・秒の組み合わせ

午前・午後などの区分は、分や秒と一緒に表示できます。フォーマッターはロケールに合わせて区分を適切な位置に配置します。

const date = new Date('2025-01-15T04:30:45');

const withMinutes = new Intl.DateTimeFormat('en-US', {
  hour: 'numeric',
  minute: 'numeric',
  hourCycle: 'h12',
  dayPeriod: 'long'
});
console.log(withMinutes.format(date));
// Output: "4:30 in the morning"

const withSeconds = new Intl.DateTimeFormat('en-US', {
  hour: 'numeric',
  minute: 'numeric',
  second: 'numeric',
  hourCycle: 'h12',
  dayPeriod: 'long'
});
console.log(withSeconds.format(date));
// Output: "4:30:45 in the morning"

時間の各要素の後に午前・午後区分などが表示されます。手動で位置や書式を調整する必要はありません。フォーマッターがロケールごとにレイアウトを自動で調整します。

ユーザーのロケールに合わせて午前・午後区分付きの時間を表示する

特定のロケールをハードコーディングするのではなく、ブラウザから取得できるユーザーの優先言語を使いましょう。navigator.language プロパティはユーザーがもっとも優先する言語を返します。

const date = new Date('2025-01-15T04:30:00');

const formatter = new Intl.DateTimeFormat(navigator.language, {
  hour: 'numeric',
  minute: 'numeric',
  hourCycle: 'h12',
  dayPeriod: 'long'
});

console.log(formatter.format(date));
// Output varies by user's locale
// For en-US: "4:30 in the morning"
// For en-GB: "4:30 at night"
// For de-DE: "4:30 morgens"
// For fr-FR: "4:30 du matin"

この方法なら、各ユーザーが普段使う表現で時間帯の区分を表示できます。ブラウザが言語設定を提供し、Intl API が各ロケールに適した表現や区切り方を適用します。

どんなときに午前・午後区分を使うべきか

午前・午後などの区分は、AM/PM よりも詳しく時間帯の情報を伝えたい場合に役立ちます。会話調の表現になり、直感的に読みやすくなります。

説明文と一緒に時間を表示するユーザーインターフェースで使うと効果的です。たとえば「午前4時30分」と表示すれば、「AM 4:30」よりも自然で分かりやすくなります。

通知やメッセージなど、会話調の表現が読みやすさを高める場面で活用しましょう。「会議は午後8時30分に始まります」の方が、「Your meeting starts at 8:30 PM」よりも読みやすくなります。

スペースの少ないコンパクトな表示、例:テーブルやチャート、情報量の多いレイアウトでは区分表示は避けましょう。AM/PM や 24 時間表記のほうが適しています。

すでに 24 時間表記で時間を表示する場合は、午前・午後区分を併記する必要はありません。時刻から十分な情報が得られます。

まとめ

dayPeriod オプションは、時間帯の呼び方を各文化に合わせて表示します。文化によって一日の区切り方は異なり、スペイン語の「madrugada」や、ドイツ語での6種類の時間帯のように、ただのAMやPM以外の呼び方が使われることもあります。

このオプションは3つの値を受け付けます。narrow は最も短い形式を、short は略式の形式を、long は完全な表現を表示します。多くのロケールでは、これら3つの値で同じ出力になる場合があります。

日中の時間帯の表現は、hourCycle: 'h12'hourCycle: 'h11' を指定して12時間表記を使う場合のみ表示されます。24時間表記では、時刻だけで十分な情報が得られるため表示されません。

ロケールごとに時間帯の呼び方や区切り時間が異なります。フォーマッターはロケールIDに基づいて自動的にこれらのルールを適用します。英国英語では4:30 AMを「夜」と扱いますが、米国英語では「朝」として扱われます。