Как переключаться между 12- и 24-часовым форматом времени
Используйте JavaScript для отображения времени с AM/PM или в 24-часовом формате в зависимости от предпочтений пользователя
Введение
В разных странах время отображается по-разному. Например, американцы обычно видят 2:30 PM, а немцы — 14:30, хотя это один и тот же момент. Если вы показываете время только в одном формате, вы предполагаете, что все пользователи привыкли к одной и той же системе.
Показ времени в непривычном формате вызывает неудобства. Пользователь, который ожидает увидеть 14:30, но видит 2:30 PM, вынужден мысленно переводить время. Тот, кто привык к 2:30 PM, но видит 14:30, сталкивается с той же проблемой. Такая когнитивная нагрузка повторяется каждый раз, когда в вашем приложении отображается время.
JavaScript предоставляет API Intl.DateTimeFormat, который автоматически форматирует время. В этом уроке объясняется, почему форматы времени различаются, как этот API управляет отображением 12- и 24-часового формата и когда стоит переопределять настройки по умолчанию для локали.
Почему форматы времени различаются в разных странах
В разных регионах сложились свои традиции отображения времени. Эти традиции отражают особенности культуры, системы образования и исторические предпосылки. Универсального формата не существует.
В США, Канаде, Австралии и на Филиппинах стандартом считается 12-часовой формат с указанием AM/PM. Послеобеденное время отображается как 2:30 PM.
В большинстве стран Европы, Латинской Америки и Азии стандартом является 24-часовой формат. То же самое время будет выглядеть как 14:30, без указания AM/PM.
В некоторых регионах используются оба формата в зависимости от ситуации. Например, в Великобритании для расписаний транспорта применяют 24-часовой формат, а в повседневной речи — 12-часовой.
Показывая время, важно учитывать ожидания пользователя в зависимости от его региона и контекста.
Что такое 12- и 24-часовой форматы
12-часовой формат делит сутки на два периода по 12 часов. Часы идут от 12 до 11, затем отсчёт начинается заново. Для обозначения времени используется AM (ante meridiem) — с полуночи до полудня, и PM (post meridiem) — с полудня до полуночи. Полночь — это 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. Новый день начинается в 00:00, а заканчивается в 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
В разных странах по умолчанию используются разные форматы. API Intl.DateTimeFormat учитывает эти настройки, но вы можете их переопределить при необходимости.
Использование опции hour12 для управления форматом времени
Опция hour12 определяет, будет ли использоваться 12-часовой формат. Установите её в true для 12-часового формата с AM/PM или в 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));
// Output: "2:30 PM"
console.log(format24.format(date));
// Output: "14:30"
Опция hour12 переопределяет поведение по умолчанию для локали. Например, хотя в США обычно используется 12-часовой формат, установка hour12: false принудительно включает 24-часовой формат.
Вы должны добавить либо hour в опции, либо использовать timeStyle, чтобы опция hour12 сработала. Без компонента времени в выводе эта опция не влияет на результат.
Использование опции 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));
// 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"
Каждое значение цикла часов даёт разный результат для одного и того же времени. Различия особенно заметны в полночь и в полдень.
Понимание четырёх значений 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-часового формата.
Сравнение отображения полуночи в разных циклах часов
Полночь наглядно демонстрирует различия между значениями цикла часов.
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
Значения h12 и h23 дают самые привычные варианты отображения для своих форматов.
Сравнение отображения полудня в разных циклах часов
Полдень тоже показывает, как различаются циклы часов.
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
Опять же, 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' // This is ignored
});
console.log(formatter.format(date));
// Output: "2:30 PM" (12-hour format from hour12: true)
Параметр 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));
// 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"
Такой подход учитывает выбор пользователя, но при этом локализует другие аспекты отображения времени, например, разделители и направление текста.
Использование 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));
// 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
Этот метод возвращает реальные настройки, которые использует форматтер после применения всех локальных значений и явных опций. Возвращаемый объект включает свойства 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 для 12-часового формата с AM/PM или в false для 24-часового формата.
Используйте опцию hourCycle для точного контроля над нумерацией часов. Значение "h12" даёт стандартный 12-часовой формат, а "h23" — стандартный 24-часовой формат.
В большинстве приложений придерживайтесь стандартов локали. Пользователи ожидают видеть время в привычном для их региона формате. Переопределяйте стандарты только если важнее единообразие для всех пользователей, чем региональные особенности.
Комбинируйте hour12 с пресетами timeStyle, чтобы управлять форматом часов и при этом использовать удобные стили для других компонентов времени.