Как переключаться между 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 → полночь
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 минута до полуночи

Разные локали используют разные форматы по умолчанию. 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));
// Вывод: "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"

Каждое значение hour cycle создаёт разный вывод для одного и того же времени. Различия становятся наиболее заметными в полночь и в полдень.

Понимание четырёх значений 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)}`);
});

// Вывод:
// 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)}`);
});

// Вывод:
// 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" (12-часовой формат из 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));
// Вывод: "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"

Этот подход учитывает выбор пользователя, при этом локализуя другие аспекты отображения времени, такие как разделители и направление текста.

Использование 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 для 12-часового формата с AM/PM или в false для 24-часового формата.

Используйте опцию hourCycle для точного контроля над нумерацией часов. Значение "h12" предоставляет стандартный 12-часовой формат, а "h23" — стандартный 24-часовой формат.

В большинстве случаев уважайте настройки локали. Пользователи ожидают, что время будет отображаться в привычном для их региона формате. Переопределяйте настройки по умолчанию только в тех случаях, когда консистентность для всех пользователей важнее, чем соблюдение региональных стандартов.

Комбинируйте hour12 с предустановками timeStyle, чтобы управлять форматом часов, используя при этом удобные предустановленные стили для других компонентов времени.