12時間形式と24時間形式の時刻表示を切り替える方法

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

はじめに

時刻は世界中で異なる表示がされます。アメリカ人は通常午後2時30分を見ますが、ドイツ人は14時30分を見ます。どちらも同じ瞬間を表しています。1つの形式のみで時刻を表示すると、すべてのユーザーが同じ慣習に従うと仮定することになります。

馴染みのない形式で時刻を表示すると、摩擦が生じます。14時30分を期待しているユーザーが午後2時30分を見ると、時刻を頭の中で変換する必要があります。午後2時30分を期待しているユーザーが14時30分を見ても、同じ問題に直面します。この認知的負荷は、アプリケーションに表示されるすべての時刻で繰り返されます。

JavaScriptは、時刻の書式設定を自動的に処理するためにIntl.DateTimeFormat APIを提供しています。このレッスンでは、時刻形式が異なる理由、APIが12時間形式と24時間形式の表示を制御する方法、およびロケールのデフォルトをオーバーライドするタイミングについて説明します。

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

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

アメリカ合衆国、カナダ、オーストラリア、およびフィリピンでは、AM/PM表示付きの12時間形式が標準です。午後の時刻は午後2時30分として表示されます。

ヨーロッパ、ラテンアメリカ、およびアジアのほとんどの地域では、24時間形式が標準です。同じ時刻は、AM/PM表示を必要とせずに14時30分として表示されます。

一部の地域では、文脈に応じて両方の形式を使用します。イギリスでは、交通機関のスケジュールには24時間形式を使用しますが、日常会話では12時間形式を使用します。

時刻を表示する際には、ユーザーの地域と文脈に対する期待に合わせる必要があります。

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

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

12:00 AM → midnight
1:00 AM → 1 hour after midnight
11:59 AM → 1 minute before noon
12:00 PM → noon
1:00 PM → 1 hour after noon
11:59 PM → 1 minute before midnight

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

00:00 → midnight
01:00 → 1 hour after midnight
11:59 → 1 minute before noon
12:00 → noon
13:00 → 1 hour after noon
23:59 → 1 minute before midnight

ロケールによってデフォルトで使用される形式は異なります。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));
// Output: "2:30 PM"

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

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

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

hourCycleオプションによる詳細な制御

hourCycleオプションは、時間のカウント方法を正確に指定することで、hour12よりも詳細な制御を提供します。このオプションは4つの値を受け入れます:"h11""h12""h23""h24"

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

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));
// Output: "0:30 AM"

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

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

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

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

4つのhourCycle値を理解する

4つのhourCycle値は、各期間内で時間がどのように番号付けされるかを定義します。

"h12"値は、1から12までの時間を持つ12時間形式を使用します。真夜中は12:00 AMとして表示され、正午は12:00 PMとして表示されます。これは米国で使用されている標準的な12時間形式です。

"h11"値は、0から11までの時間を持つ12時間形式を使用します。真夜中は0:00 AMとして表示され、正午は0:00 PMとして表示されます。この形式はあまり一般的ではありませんが、一部のコンテキストで使用されます。

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

"h24"値は、1から24までの時間を持つ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)}`);
});

// Output:
// 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)}`);
});

// Output:
// 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'  // This is ignored
});

console.log(formatter.format(date));
// Output: "2:30 PM" (12-hour format from hour12: true)

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));
// Output: "2:30 PM" (US default: 12-hour)

console.log(deFormatter.format(date));
// Output: "14:30" (German default: 24-hour)

console.log(jpFormatter.format(date));
// Output: "14:30" (Japanese default: 24-hour)

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

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

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

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

// Force German locale to use 12-hour format
const de12 = new Intl.DateTimeFormat('de-DE', {
  hour: 'numeric',
  minute: 'numeric',
  hour12: true
});

// Force US locale to use 24-hour format
const us24 = new Intl.DateTimeFormat('en-US', {
  hour: 'numeric',
  minute: 'numeric',
  hour12: false
});

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

console.log(us24.format(date));
// Output: "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));
// Output varies by user's locale
// For en-US: "2:30 PM"
// For de-DE: "14:30"
// For ja-JP: "14:30"

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

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

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

// Always use 24-hour format for flight times
const formatter = new Intl.DateTimeFormat(navigator.language, {
  hour: 'numeric',
  minute: 'numeric',
  hour12: false
});

const departureTime = new Date('2025-03-15T14:30:00');
console.log(`Departure: ${formatter.format(departureTime)}`);
// Output: "Departure: 14:30" (for all locales)

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

また、ユーザーが明示的に設定を選択した場合にも、デフォルトを上書きできます。アプリケーションが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));
// Output: "2:30 PM"

console.log(formatTime(time, true));
// Output: "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));
// Output: "2:30 PM"

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

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

console.log(medium24.format(date));
// Output: "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)}`);
});

// Output:
// 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);
// Output: "h12"

console.log(options.hour12);
// Output: 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);

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

覚えておくべきこと

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

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

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

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