如何在 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 小时制的显示,以及何时需要覆盖区域设置的默认值。
为什么时间格式因地区而异
不同地区发展了不同的时间显示惯例。这些惯例反映了文化习俗、教育体系和历史先例。没有一种格式是通用的。
在美国、加拿大、澳大利亚和菲律宾,12 小时制(带有 AM/PM 指示符)是标准。下午的时间显示为 2:30 PM。
在大多数欧洲、拉丁美洲和亚洲地区,24 小时制是标准。同一时间显示为 14:30,无需 AM/PM 指示符。
某些地区根据上下文使用两种格式。英国在交通时刻表中使用 24 小时制,但在日常对话中使用 12 小时制。
显示时间时,需要匹配用户所在地区和上下文的期望。
什么是 12 小时制和 24 小时制
12 小时制将一天分为两个 12 小时的时段。小时从 12 到 11,然后重新开始。该系统使用 AM(上午)表示午夜到中午,使用 PM(下午)表示中午到午夜。午夜从 12:00 AM 开始,中午为 12:00 PM。
12:00 AM → 午夜
1:00 AM → 午夜后 1 小时
11:59 AM → 中午前 1 分钟
12:00 PM → 中午
1:00 PM → 中午后 1 小时
11:59 PM → 午夜前 1 分钟
24 小时制从 0 到 23 连续计时。午夜从 00:00 开始,全天结束于 23:59。无需 AM/PM 指示符,因为每个小时都有唯一的编号。
00:00 → 午夜
01:00 → 午夜后 1 小时
11:59 → 中午前 1 分钟
12:00 → 中午
13:00 → 中午后 1 小时
23:59 → 午夜前 1 分钟
不同的区域设置默认使用不同的格式。Intl.DateTimeFormat API 遵循这些默认值,但在需要时允许覆盖它们。
使用 hour12 选项控制时间格式
hour12 选项用于控制是否使用 12 小时制。将其设置为 true 可使用带有 AM/PM 的 12 小时制,设置为 false 则使用 24 小时制。
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"。
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));
// 输出: "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"
每个小时周期值会为相同的时间生成不同的输出。这些差异在午夜和中午时最为明显。
了解四种 hourCycle 值
四种 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。这种格式较为罕见,但在某些技术场景中会出现。
大多数应用程序使用 "h12" 表示 12 小时制或 "h23" 表示 24 小时制。
比较不同 hourCycle 值下的午夜时间
午夜最能清楚地展示 hourCycle 值之间的差异。
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
h12 和 h23 值分别为其对应格式生成了最常见的表示。
比较不同 hourCycle 值下的正午时间
中午时间也展示了小时周期的不同。
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
同样,h12 和 h23 生成标准表示,而 h11 使用 0 表示中午时间。
hour12 和 hourCycle 的交互
当同时指定 hour12 和 hourCycle 时,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 小时制格式,覆盖了 hourCycle: 'h23' 设置,该设置通常会生成 24 小时制格式。
在实际使用中,可以使用 hour12 进行简单控制,或使用 hourCycle 进行精确控制,但不要同时使用两者。
遵循区域设置的默认值
当同时省略 hour12 和 hourCycle 时,格式化器会使用区域设置的默认时间格式。
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(`Departure: ${formatter.format(departureTime)}`);
// 输出: "Departure: 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"
这种模式尊重用户的选择,同时仍然本地化时间显示的其他方面,例如分隔符字符和文本方向。
使用 hour12 和 timeStyle
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
此方法返回格式化器在解析所有区域默认值和显式选项后实际使用的设置。返回的对象在时间组件存在时包括 hourCycle 和 hour12 属性。
在模板中格式化时间
您可以在任何向用户显示时间信息的地方使用格式化时间。这包括将时间插入到 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 小时制之间切换。将其设置为 true 可显示带有 AM/PM 的 12 小时制,或设置为 false 显示 24 小时制。
使用 hourCycle 选项精确控制小时编号。"h12" 值提供标准的 12 小时制,"h23" 提供标准的 24 小时制。
在大多数应用中尊重区域默认设置。用户期望时间以其所在地区熟悉的格式显示。仅在一致性对所有用户比尊重区域惯例更重要时才覆盖默认设置。
将 hour12 与 timeStyle 预设结合使用,可以在控制小时格式的同时方便地使用其他时间组件的预设样式。