Как форматировать время в локали пользователя
Используйте JavaScript для отображения времени в соответствии с региональными стандартами каждого пользователя
Введение
Время отображается по-разному в разных странах. Американцы обычно видят 3:30 PM как 3:30 PM, а большинство европейцев ожидают 15:30. Если вы жёстко задаёте формат времени, вы предполагаете, что все пользователи придерживаются одного стандарта.
Показ времени в непривычном формате сбивает с толку. Пользователь, привыкший к 24-часовому формату, увидев 3:30 PM, должен мысленно переводить его, чтобы понять, утро это или вечер. Такая когнитивная нагрузка накапливается при каждом отображении времени в вашем приложении.
JavaScript предоставляет API Intl.DateTimeFormat, который автоматически форматирует время. В этом уроке объясняется, почему форматы времени различаются в разных культурах, как работает этот API и как правильно форматировать время для любой локали.
Почему форматы времени различаются по локалям
В разных регионах сложились свои традиции отображения времени. Эти стандарты отражают исторические особенности, образовательные системы и культурные предпочтения. Универсального формата не существует.
В США, Канаде, Австралии и на Филиппинах используется 12-часовой формат с указателями AM и PM. 3:30 дня отображается как 3:30 PM.
В большинстве европейских стран, Латинской Америке и Азии используется 24-часовой формат без AM и PM. То же время отображается как 15:30.
Символ-разделитель между часами и минутами тоже может отличаться. В англоязычных странах обычно используется двоеточие, а в некоторых локалях — точка или другой знак препинания.
Способ отображения AM и PM тоже различается. В английском используются AM и PM, в испанском — a.m. и p.m., а в некоторых локалях эти обозначения ставятся перед временем, а не после.
При отображении времени важно учитывать ожидания пользователя как по формату часов, так и по специфическим правилам форматирования.
Использование Intl.DateTimeFormat для форматирования времени
Конструктор Intl.DateTimeFormat создаёт форматтер, который применяет локальные правила форматирования. Чтобы отформатировать время, передайте идентификатор локали первым аргументом и укажите параметры, связанные со временем, вторым аргументом.
const formatter = new Intl.DateTimeFormat('en-US', {
hour: 'numeric',
minute: 'numeric'
});
const date = new Date('2025-03-15T15:30:00');
console.log(formatter.format(date));
// Output: "3:30 PM"
Это создаёт форматтер для американского английского, который отображает часы и минуты. Опции hour и minute указывают форматтеру включать эти компоненты. Метод format() преобразует объект Date в строку с нужным форматированием.
Конструктор Date принимает строку даты и времени в формате ISO 8601, например 2025-03-15T15:30:00. Это создаёт объект Date, который соответствует 15:30 15 марта 2025 года. Форматтер затем преобразует это значение во временную строку с учётом локали.
Форматирование одного и того же времени для разных локалей
Вы можете отформатировать одно и то же время для разных локалей, изменяя идентификатор локали, передаваемый в конструктор.
const date = new Date('2025-03-15T15:30:00');
const usFormatter = new Intl.DateTimeFormat('en-US', {
hour: 'numeric',
minute: 'numeric'
});
console.log(usFormatter.format(date));
// Output: "3:30 PM"
const gbFormatter = new Intl.DateTimeFormat('en-GB', {
hour: 'numeric',
minute: 'numeric'
});
console.log(gbFormatter.format(date));
// Output: "15:30"
const deFormatter = new Intl.DateTimeFormat('de-DE', {
hour: 'numeric',
minute: 'numeric'
});
console.log(deFormatter.format(date));
// Output: "15:30"
const frFormatter = new Intl.DateTimeFormat('fr-FR', {
hour: 'numeric',
minute: 'numeric'
});
console.log(frFormatter.format(date));
// Output: "15:30"
Каждый форматтер использует свои правила. Американский форматтер применяет 12-часовой формат с AM/PM. Британский, немецкий и французский форматтеры используют 24-часовой формат без AM/PM.
Вам не нужно знать, какой формат используется в каждой локали. API автоматически учитывает эти детали на основе идентификатора локали.
Отображение секунд во времени
Вы можете добавить опцию second, чтобы показывать секунды вместе с часами и минутами.
const formatter = new Intl.DateTimeFormat('en-US', {
hour: 'numeric',
minute: 'numeric',
second: 'numeric'
});
const date = new Date('2025-03-15T15:30:45');
console.log(formatter.format(date));
// Output: "3:30:45 PM"
Опция second работает так же, как hour и minute. Установите её в 'numeric', чтобы добавить секунды в вывод.
Управление добавлением нулей с помощью 2-digit
Опции hour, minute и second принимают два значения: 'numeric' и '2-digit'. Значение 'numeric' отображает цифры без добавления нулей, а '2-digit' всегда показывает две цифры с ведущим нулём.
const date = new Date('2025-03-15T09:05:03');
const numericFormatter = new Intl.DateTimeFormat('en-US', {
hour: 'numeric',
minute: 'numeric',
second: 'numeric'
});
console.log(numericFormatter.format(date));
// Output: "9:05:03 AM"
const twoDigitFormatter = new Intl.DateTimeFormat('en-US', {
hour: '2-digit',
minute: '2-digit',
second: '2-digit'
});
console.log(twoDigitFormatter.format(date));
// Output: "09:05:03 AM"
Числовой форматтер отображает 9:05:03 AM с одной цифрой для часа. Форматтер с двумя цифрами показывает 09:05:03 AM с ведущим нулём для часа. В обоих случаях минуты и секунды отображаются двумя цифрами, так как эти значения обычно дополняются нулями независимо от настройки.
Принудительный выбор 12- или 24-часового формата
По умолчанию API использует формат времени, предпочтительный для локали. Это можно переопределить с помощью опции hour12.
const date = new Date('2025-03-15T15:30:00');
const hour12Formatter = new Intl.DateTimeFormat('en-GB', {
hour: 'numeric',
minute: 'numeric',
hour12: true
});
console.log(hour12Formatter.format(date));
// Output: "3:30 pm"
const hour24Formatter = new Intl.DateTimeFormat('en-US', {
hour: 'numeric',
minute: 'numeric',
hour12: false
});
console.log(hour24Formatter.format(date));
// Output: "15:30"
Установка hour12: true принудительно включает 12-часовой формат даже для локалей, где обычно используется 24-часовой. Установка hour12: false принудительно включает 24-часовой формат даже для локалей, где обычно используется 12-часовой.
Локаль по-прежнему определяет другие детали форматирования, такие как пунктуация и пробелы. Форматтер для Великобритании с hour12: true отображает 3:30 pm с маленькими буквами pm, а форматтер для США покажет 3:30 PM с заглавными PM.
Форматирование времени для локали пользователя
Вместо жёсткой привязки к определённой локали можно использовать предпочтительный язык пользователя из браузера. Свойство navigator.language возвращает основной языковой приоритет пользователя.
const userLocale = navigator.language;
const formatter = new Intl.DateTimeFormat(userLocale, {
hour: 'numeric',
minute: 'numeric'
});
const date = new Date('2025-03-15T15:30:00');
console.log(formatter.format(date));
// Output varies by user's locale
// For en-US: "3:30 PM"
// For en-GB: "15:30"
// For de-DE: "15:30"
// For fr-FR: "15:30"
Такой подход позволяет отображать время в соответствии с ожиданиями каждого пользователя без необходимости вручную выбирать локаль. Браузер предоставляет языковые предпочтения, а Intl API применяет соответствующие правила форматирования.
Вы также можете передать весь массив предпочитаемых языков, чтобы включить поведение с резервным выбором.
const formatter = new Intl.DateTimeFormat(navigator.languages, {
hour: 'numeric',
minute: 'numeric'
});
const date = new Date('2025-03-15T15:30:00');
console.log(formatter.format(date));
API использует первую поддерживаемую локаль из массива. Это обеспечивает более корректную обработку резервных вариантов, если предпочтительный язык пользователя недоступен.
Создание времени для форматирования
Вы можете создать объекты Date с информацией о времени несколькими способами. Самый надёжный — использовать строки даты и времени в формате ISO 8601.
const time1 = new Date('2025-03-15T09:00:00');
const time2 = new Date('2025-03-15T15:30:00');
const time3 = new Date('2025-03-15T23:45:30');
const formatter = new Intl.DateTimeFormat('en-US', {
hour: 'numeric',
minute: 'numeric'
});
console.log(formatter.format(time1));
// Output: "9:00 AM"
console.log(formatter.format(time2));
// Output: "3:30 PM"
console.log(formatter.format(time3));
// Output: "11:45 PM"
Строки даты и времени ISO 8601 используют формат YYYY-MM-DDTHH:MM:SS. Символ T разделяет дату и время. Этот формат однозначен и работает одинаково во всех локалях и часовых поясах.
Форматирование времени из временных меток
Вы также можете создать объекты Date из Unix-временных меток. Unix-временная метка — это количество миллисекунд с 1 января 1970 года по UTC.
const timestamp = 1710515400000; // March 15, 2025 at 3:30 PM
const date = new Date(timestamp);
const formatter = new Intl.DateTimeFormat('en-US', {
hour: 'numeric',
minute: 'numeric'
});
console.log(formatter.format(date));
// Output: "3:30 PM"
Этот способ подходит, если вы получаете временные метки из API, баз данных или других систем, где время представлено числами.
Вы также можете передать временную метку напрямую в метод format() без создания объекта Date.
const formatter = new Intl.DateTimeFormat('en-US', {
hour: 'numeric',
minute: 'numeric'
});
const timestamp = 1710515400000;
console.log(formatter.format(timestamp));
// Output: "3:30 PM"
API принимает как объекты Date, так и временные метки. Используйте тот способ, который удобнее для вашего кода.
Форматирование текущего времени
Чтобы отформатировать текущее время, создайте объект Date без аргументов. Это создаст объект Date, представляющий текущий момент.
const formatter = new Intl.DateTimeFormat('en-US', {
hour: 'numeric',
minute: 'numeric',
second: 'numeric'
});
const now = new Date();
console.log(formatter.format(now));
// Output: "3:45:12 PM" (or current time when run)
Вы также можете передать Date.now() напрямую — он вернёт текущую временную метку в виде числа.
const formatter = new Intl.DateTimeFormat('en-US', {
hour: 'numeric',
minute: 'numeric',
second: 'numeric'
});
console.log(formatter.format(Date.now()));
// Output: "3:45:12 PM" (or current time when run)
Оба способа дают одинаковый результат.
Повторное использование форматтеров для производительности
Создание нового экземпляра Intl.DateTimeFormat включает загрузку данных локали и обработку опций. Если нужно форматировать несколько времён с одной локалью и настройками, создайте форматтер один раз и используйте его повторно.
const formatter = new Intl.DateTimeFormat('en-US', {
hour: 'numeric',
minute: 'numeric'
});
const times = [
new Date('2025-03-15T09:00:00'),
new Date('2025-03-15T12:30:00'),
new Date('2025-03-15T18:45:00')
];
times.forEach(time => {
console.log(formatter.format(time));
});
// Output:
// "9:00 AM"
// "12:30 PM"
// "6:45 PM"
Этот способ эффективнее, чем создавать новый форматтер каждый раз. Разница в производительности становится заметной при форматировании массивов с сотнями или тысячами значений времени.
Форматирование времени в шаблонах
Вы можете использовать Intl.DateTimeFormat в любом месте, где отображаете время для пользователей. Это включает вставку отформатированного времени в HTML-шаблоны, показ времени в таблицах или отображение временных меток в интерфейсе.
const formatter = new Intl.DateTimeFormat(navigator.language, {
hour: 'numeric',
minute: 'numeric'
});
const eventStart = new Date('2025-03-15T14:00:00');
const eventEnd = new Date('2025-03-15T16:30:00');
document.getElementById('start-time').textContent = formatter.format(eventStart);
document.getElementById('end-time').textContent = formatter.format(eventEnd);
Отформатированные строки работают как любые другие строковые значения. Их можно вставлять в текст, атрибуты или любой другой контекст, где вы показываете информацию пользователям.