12時間形式と24時間形式の切り替え方法

JavaScriptを使用して、ユーザー設定に応じてAM/PM付きまたは24時間形式で時刻を表示する方法

はじめに

時間の表示は世界各地で異なります。アメリカ人は通常「2:30 PM」と表示しますが、ドイツ人は「14:30」と表示し、どちらも同じ瞬間を表しています。一つの形式だけで時間を表示すると、すべてのユーザーが同じ表記法に従っていると仮定することになります。

慣れない形式で時間を表示すると摩擦が生じます。「14:30」を期待するユーザーが「2:30 PM」を見ると、頭の中で時間を変換しなければなりません。「2:30 PM」を期待するユーザーが「14:30」を見る場合も同じ問題に直面します。この認知的負荷は、アプリケーションに表示されるすべての時間に対して繰り返されます。

JavaScriptは時間の書式設定を自動的に処理するIntl.DateTimeFormat APIを提供しています。このレッスンでは、時間の形式がなぜ地域によって異なるのか、APIがどのように12時間表示と24時間表示を制御するのか、そしていつロケールのデフォルトを上書きすべきかを説明します。

ロケールによって時間形式が異なる理由

異なる地域では時間表示のための異なる慣習が発展してきました。これらの慣習は文化的慣行、教育システム、歴史的先例を反映しています。普遍的な単一の形式は存在しません。

アメリカ合衆国、カナダ、オーストラリア、フィリピンでは、AM/PM表示を伴う12時間形式が標準です。午後の時間は「2:30 PM」と表示されます。

ヨーロッパ、ラテンアメリカ、アジアのほとんどの地域では、24時間形式が標準です。同じ時間は「14:30」と表示され、AM/PM表示は必要ありません。

一部の地域では、コンテキストによって両方の形式が使用されます。イギリスでは交通機関のスケジュールには24時間形式を使用しますが、日常会話では12時間形式を使用します。

時間を表示する際には、ユーザーの地域やコンテキストに対する期待に合わせる必要があります。

12時間形式と24時間形式の意味

12時間形式は1日を2つの12時間の期間に分けます。時間は12から11まで進み、その後再び始まります。このシステムでは午前0時から正午までをAM(午前)、正午から午前0時までをPM(午後)と表します。午前0時は12:00 AMから始まり、正午は12:00 PMに発生します。

12:00 AM → 午前0時
1:00 AM → 午前0時から1時間後
11:59 AM → 正午の1分前
12:00 PM → 正午
1:00 PM → 正午から1時間後
11:59 PM → 午前0時の1分前

24時間形式は時間を0から23まで連続的にカウントします。午前0時は00:00から始まり、1日は23:59で終わります。各時間には固有の番号があるため、AM/PM表示は必要ありません。

00:00 → 午前0時
01:00 → 午前0時から1時間後
11:59 → 正午の1分前
12:00 → 正午
13:00 → 正午から1時間後
23:59 → 午前0時の1分前

異なるロケールではデフォルトで異なる形式が使用されます。Intl.DateTimeFormat APIはこれらのデフォルトを尊重しますが、必要に応じてそれらを上書きすることができます。

hour12オプションを使用して時間形式を制御する

hour12オプションは12時間形式を使用するかどうかを制御します。AM/PM付きの12時間形式にはtrueを、24時間形式にはfalseを設定します。

const date = new Date('2025-03-15T14:30:00');

const format12 = new Intl.DateTimeFormat('en-US', {
  hour: 'numeric',
  minute: 'numeric',
  hour12: true
});

const format24 = new Intl.DateTimeFormat('en-US', {
  hour: 'numeric',
  minute: 'numeric',
  hour12: false
});

console.log(format12.format(date));
// 出力: "2:30 PM"

console.log(format24.format(date));
// 出力: "14:30"

hour12オプションはロケールのデフォルト動作を上書きします。米国英語は通常12時間形式を使用しますが、hour12: falseを設定すると24時間形式が強制されます。

hour12オプションを有効にするには、オプションにhourを含めるか、timeStyleを使用する必要があります。出力に時間コンポーネントがない場合、このオプションは影響を与えません。

hourCycleオプションを使用した詳細な制御

hourCycleオプションはhour12よりも詳細な制御を提供し、時間の数え方を正確に指定します。"h11""h12""h23""h24"の4つの値を受け付けます。

const date = new Date('2025-03-15T00:30:00'); // 午前12:30

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

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

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

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

console.log(h11.format(date));
// 出力: "0:30 AM"

console.log(h12.format(date));
// 出力: "12:30 AM"

console.log(h23.format(date));
// 出力: "00:30"

console.log(h24.format(date));
// 出力: "24:30"

各時間サイクル値は同じ時間に対して異なる出力を生成します。これらの違いは真夜中と正午で最も顕著になります。

4つのhourCycle値を理解する

4つのhourCycle値は、各期間内での時間の表記方法を定義します。

"h12"値は12時間形式を使用し、時間は1から12までです。深夜は12:00 AM、正午は12:00 PMと表示されます。これはアメリカで標準的に使用される12時間形式です。

"h11"値は12時間形式を使用し、時間は0から11までです。深夜は0:00 AM、正午は0:00 PMと表示されます。この形式はあまり一般的ではありませんが、特定の状況で使用されることがあります。

"h23"値は24時間形式を使用し、時間は0から23までです。深夜は00:00と表示され、一日は23:59で終わります。これはヨーロッパやアジアのほとんどの地域で使用される標準的な24時間形式です。

"h24"値は24時間形式を使用し、時間は1から24までです。深夜は前日の視点から24:00と表示されます。この形式は稀ですが、一部の技術的な状況で使用されることがあります。

ほとんどのアプリケーションでは、12時間形式には"h12"、24時間形式には"h23"のいずれかが使用されます。

時間サイクル間での深夜の時間比較

深夜は時間サイクル値の違いを最も明確に示します。

const midnight = new Date('2025-03-15T00:00:00');

const cycles = ['h11', 'h12', 'h23', 'h24'];

cycles.forEach(cycle => {
  const formatter = new Intl.DateTimeFormat('en-US', {
    hour: 'numeric',
    minute: 'numeric',
    second: 'numeric',
    hourCycle: cycle
  });

  console.log(`${cycle}: ${formatter.format(midnight)}`);
});

// 出力:
// h11: 0:00:00 AM
// h12: 12:00:00 AM
// h23: 00:00:00
// h24: 24:00:00

h12h23の値は、それぞれの形式で最も馴染みのある表現を生成します。

時間サイクル間での正午の時間比較

正午も時間周期の違いを示しています。

const noon = new Date('2025-03-15T12:00:00');

const cycles = ['h11', 'h12', 'h23', 'h24'];

cycles.forEach(cycle => {
  const formatter = new Intl.DateTimeFormat('en-US', {
    hour: 'numeric',
    minute: 'numeric',
    second: 'numeric',
    hourCycle: cycle
  });

  console.log(`${cycle}: ${formatter.format(noon)}`);
});

// 出力:
// h11: 0:00:00 PM
// h12: 12:00:00 PM
// h23: 12:00:00
// h24: 12:00:00

ここでも、h12h23は標準的な表現を生成しますが、h11は正午の時間に0を使用します。

hour12とhourCycleの相互作用

hour12hourCycleの両方を指定した場合、hour12オプションが優先され、hourCycleオプションは無視されます。

const date = new Date('2025-03-15T14:30:00');

const formatter = new Intl.DateTimeFormat('en-US', {
  hour: 'numeric',
  minute: 'numeric',
  hour12: true,
  hourCycle: 'h23'  // これは無視されます
});

console.log(formatter.format(date));
// 出力: "2:30 PM" (hour12: trueによる12時間形式)

hour12: trueの設定は12時間形式を強制し、通常は24時間形式を生成するhourCycle: 'h23'の設定を上書きします。

実際には、簡単な制御にはhour12を、正確な制御にはhourCycleを使用しますが、両方を同時に使用することはありません。

ロケールのデフォルトを尊重する

hour12hourCycleの両方を省略すると、フォーマッタはロケールのデフォルトの時間形式を使用します。

const date = new Date('2025-03-15T14:30:00');

const usFormatter = new Intl.DateTimeFormat('en-US', {
  hour: 'numeric',
  minute: 'numeric'
});

const deFormatter = new Intl.DateTimeFormat('de-DE', {
  hour: 'numeric',
  minute: 'numeric'
});

const jpFormatter = new Intl.DateTimeFormat('ja-JP', {
  hour: 'numeric',
  minute: 'numeric'
});

console.log(usFormatter.format(date));
// 出力: "2:30 PM" (米国のデフォルト: 12時間制)

console.log(deFormatter.format(date));
// 出力: "14:30" (ドイツのデフォルト: 24時間制)

console.log(jpFormatter.format(date));
// 出力: "14:30" (日本のデフォルト: 24時間制)

米国のロケールはデフォルトで12時間形式ですが、ドイツと日本のロケールはデフォルトで24時間形式です。これらのデフォルトを尊重することで、各地域のユーザーに最も馴染みのある体験を提供できます。

ロケールのデフォルト設定の上書き

ロケールのデフォルト時間形式は、hour12またはhourCycleを明示的に設定することで上書きできます。

const date = new Date('2025-03-15T14:30:00');

// ドイツロケールを12時間形式に強制する
const de12 = new Intl.DateTimeFormat('de-DE', {
  hour: 'numeric',
  minute: 'numeric',
  hour12: true
});

// 米国ロケールを24時間形式に強制する
const us24 = new Intl.DateTimeFormat('en-US', {
  hour: 'numeric',
  minute: 'numeric',
  hour12: false
});

console.log(de12.format(date));
// 出力: "2:30 PM"

console.log(us24.format(date));
// 出力: "14:30"

このアプローチは、ユーザーのロケールに関係なく特定の時間形式を強制する必要がある場合に有効です。

ロケールのデフォルト設定を尊重すべき場合

ほとんどのアプリケーションではロケールのデフォルト設定を尊重すべきです。各地域のユーザーは、時間が慣れ親しんだ形式で表示されることを期待しています。これらのデフォルト設定を上書きすると混乱を招きます。

ユーザー自身の地域に時間を表示する際は、フォーマッタにロケールのデフォルト時間形式を使用させましょう。

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

const time = new Date('2025-03-15T14:30:00');
console.log(formatter.format(time));
// 出力はユーザーのロケールによって異なる
// en-USの場合: "2:30 PM"
// de-DEの場合: "14:30"
// ja-JPの場合: "14:30"

このアプローチは、設定を必要とせずに各ユーザーの期待に自動的に適応します。

ロケールのデフォルト設定を上書きすべき場合

アプリケーションがすべてのユーザーに対して一貫性を必要とする場合は、ロケールのデフォルト設定を上書きしましょう。交通システム、軍事アプリケーション、技術的なツールでは、ロケールに関係なく24時間形式が必要になることがよくあります。

// フライト時間には常に24時間形式を使用する
const formatter = new Intl.DateTimeFormat(navigator.language, {
  hour: 'numeric',
  minute: 'numeric',
  hour12: false
});

const departureTime = new Date('2025-03-15T14:30:00');
console.log(`出発: ${formatter.format(departureTime)}`);
// 出力: "出発: 14:30"(すべてのロケールで)

これにより、スケジュール、ログ、タイムスタンプなど、ユーザーが正確に参照する必要がある時間を表示する際の一貫性が確保されます。

ユーザーが明示的に設定を選択した場合にもデフォルト設定を上書きできます。アプリケーションが12時間形式と24時間形式を選択する設定を提供している場合は、ロケールのデフォルトではなくその設定を使用しましょう。

function formatTime(date, userPrefers24Hour) {
  const formatter = new Intl.DateTimeFormat(navigator.language, {
    hour: 'numeric',
    minute: 'numeric',
    hour12: !userPrefers24Hour
  });

  return formatter.format(date);
}

const time = new Date('2025-03-15T14:30:00');

console.log(formatTime(time, false));
// 出力: "2:30 PM"

console.log(formatTime(time, true));
// 出力: "14:30"

このパターンは、区切り文字やテキストの方向などの時間表示の他の側面をローカライズしながら、ユーザーの選択を尊重します。

timeStyleとhour12の併用

hour12オプションはtimeStyleプリセットスタイルと併用できます。これにより、便利なプリセットスタイルを使用しながら時間形式を制御できます。

const date = new Date('2025-03-15T14:30:45');

const short12 = new Intl.DateTimeFormat('en-US', {
  timeStyle: 'short',
  hour12: true
});

const short24 = new Intl.DateTimeFormat('en-US', {
  timeStyle: 'short',
  hour12: false
});

const medium12 = new Intl.DateTimeFormat('en-US', {
  timeStyle: 'medium',
  hour12: true
});

const medium24 = new Intl.DateTimeFormat('en-US', {
  timeStyle: 'medium',
  hour12: false
});

console.log(short12.format(date));
// 出力: "2:30 PM"

console.log(short24.format(date));
// 出力: "14:30"

console.log(medium12.format(date));
// 出力: "2:30:45 PM"

console.log(medium24.format(date));
// 出力: "14:30:45"

このアプローチでは、プリセットスタイルと明示的な時間形式の制御を組み合わせることでフォーマットが簡素化されます。

複数のロケールでの時間フォーマット

アプリケーションが複数の地域のユーザーにサービスを提供する場合、各ロケールの慣習に従って時間をフォーマットします。

const date = new Date('2025-03-15T14:30:00');

const locales = [
  { code: 'en-US', name: 'United States' },
  { code: 'en-GB', name: 'United Kingdom' },
  { code: 'de-DE', name: 'Germany' },
  { code: 'ja-JP', name: 'Japan' }
];

locales.forEach(locale => {
  const formatter = new Intl.DateTimeFormat(locale.code, {
    hour: 'numeric',
    minute: 'numeric'
  });

  console.log(`${locale.name}: ${formatter.format(date)}`);
});

// 出力:
// United States: 2:30 PM
// United Kingdom: 14:30
// Germany: 14:30
// Japan: 14:30

各ロケールは自動的に好ましい形式を使用します。どの地域がどの形式を使用するかを知る必要はありません。

解決された時間サイクルの確認

resolvedOptions()を呼び出すことで、フォーマッタが実際に使用する時間サイクルを確認できます。

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

const options = formatter.resolvedOptions();
console.log(options.hourCycle);
// 出力: "h12"

console.log(options.hour12);
// 出力: true

このメソッドは、すべてのロケールのデフォルト設定と明示的なオプションを解決した後、フォーマッタが使用する実際の設定を返します。時間コンポーネントが存在する場合、返されるオブジェクトにはhourCyclehour12の両方のプロパティが含まれます。

テンプレートでの時刻のフォーマット

ユーザーに時間情報を表示する場所であればどこでも、フォーマットされた時刻を使用できます。これには、HTMLへの時刻の挿入、ログでのタイムスタンプの表示、スケジュールの表示などが含まれます。

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

const meetingTime = new Date('2025-03-15T14:30:00');
const deadlineTime = new Date('2025-03-15T17:00:00');

document.getElementById('meeting').textContent = formatter.format(meetingTime);
document.getElementById('deadline').textContent = formatter.format(deadlineTime);

フォーマットされた文字列は他の文字列値と同様に機能します。テキストコンテンツ、属性、またはユーザーに情報を表示するあらゆるコンテキストに挿入できます。

覚えておくべきこと

12時間形式と24時間形式を切り替えるには、hour12オプションを使用します。AM/PM付きの12時間形式にはtrueを、24時間形式にはfalseを設定します。

時間の表記を正確に制御するには、hourCycleオプションを使用します。"h12"値は標準的な12時間形式を提供し、"h23"は標準的な24時間形式を提供します。

ほとんどのアプリケーションではロケールのデフォルト設定を尊重してください。ユーザーは自分の地域で馴染みのある形式で時刻が表示されることを期待しています。地域の慣習を尊重することよりも、すべてのユーザーにわたる一貫性が重要な場合にのみ、デフォルト設定を上書きしてください。

hour12timeStyleプリセットを組み合わせて、時間形式を制御しながら、他の時間コンポーネントには便利なプリセットスタイルを使用します。