Как форматировать даты в локали пользователя

Используйте JavaScript для отображения дат в соответствии с региональными стандартами каждого пользователя

Введение

Даты выглядят по-разному в разных странах. Американцы пишут 15 марта 2025 года как 3/15/2025, европейцы — как 15/03/2025, а японские пользователи ожидают увидеть 2025/3/15. Если вы жёстко задаёте формат даты, вы предполагаете, что все пользователи придерживаются одного стандарта.

Показ дат в непривычном формате сбивает с толку. Пользователь, который видит 3/15/2025, ожидая 15/03/2025, вынужден задуматься, означает ли дата 15 марта или несуществующий 15-й месяц. Такая когнитивная нагрузка накапливается на каждой дате в вашем приложении.

JavaScript предоставляет API Intl.DateTimeFormat для автоматического форматирования дат. В этом уроке объясняется, почему форматы дат различаются в разных культурах, как работает этот API и как правильно форматировать даты для любой локали.

Почему форматы дат различаются по локалям

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

В США даты записывают в формате месяц-день-год. 15 марта 2025 года выглядит как 3/15/2025.

В большинстве европейских стран, включая Великобританию, Германию, Францию и Испанию, используется формат день-месяц-год. Та же дата выглядит как 15/03/2025.

В Японии, Китае и Корее даты записывают в формате год-месяц-день. Дата выглядит как 2025/3/15.

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

Названия месяцев также различаются в зависимости от языка. Март называется "March" на английском, "März" на немецком, "mars" на французском, "marzo" на испанском и "3月" на японском.

При отображении дат важно учитывать ожидания пользователя как по порядку компонентов, так и по конкретным правилам форматирования.

Использование Intl.DateTimeFormat для форматирования дат

Конструктор Intl.DateTimeFormat создаёт форматтер дат, который применяет локальные правила форматирования. Передайте идентификатор локали первым аргументом, затем вызовите метод format() с объектом Date.

const formatter = new Intl.DateTimeFormat('en-US');
const date = new Date('2025-03-15');
console.log(formatter.format(date));
// Output: "3/15/2025"

Это создаёт форматтер для американского английского, который использует порядок месяц-день-год со слэшами. Метод format() преобразует объект Date в строку с нужным форматированием.

Конструктор Date принимает строку даты в формате ISO 8601, например 2025-03-15. Это создаёт объект Date, представляющий 15 марта 2025 года в полночь по UTC. Форматтер затем преобразует это в строку, соответствующую локали.

Форматирование одной и той же даты для разных локалей

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

const date = new Date('2025-03-15');

const usFormatter = new Intl.DateTimeFormat('en-US');
console.log(usFormatter.format(date));
// Output: "3/15/2025"

const gbFormatter = new Intl.DateTimeFormat('en-GB');
console.log(gbFormatter.format(date));
// Output: "15/03/2025"

const deFormatter = new Intl.DateTimeFormat('de-DE');
console.log(deFormatter.format(date));
// Output: "15.3.2025"

const jpFormatter = new Intl.DateTimeFormat('ja-JP');
console.log(jpFormatter.format(date));
// Output: "2025/3/15"

Каждый форматтер применяет свои правила. Американский форматтер использует месяц-день-год со слэшами. Британский — день-месяц-год со слэшами. Немецкий — день-месяц-год с точками. Японский — год-месяц-день со слэшами.

Вам не нужно знать, какой порядок или разделители используются в каждой локали. API автоматически учитывает эти детали на основе идентификатора локали.

Форматирование дат для локали пользователя

Вместо жёстко заданной локали можно использовать предпочтительный язык пользователя из браузера. Свойство navigator.language возвращает основной языковой приоритет пользователя.

const userLocale = navigator.language;
const formatter = new Intl.DateTimeFormat(userLocale);
const date = new Date('2025-03-15');

console.log(formatter.format(date));
// Output varies by user's locale
// For en-US: "3/15/2025"
// For en-GB: "15/03/2025"
// For de-DE: "15.3.2025"
// For ja-JP: "2025/3/15"

Этот подход отображает даты так, как ожидает каждый пользователь, без необходимости вручную выбирать язык. Браузер передаёт языковые предпочтения, а API Intl применяет соответствующие правила форматирования.

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

const formatter = new Intl.DateTimeFormat(navigator.languages);
const date = new Date('2025-03-15');
console.log(formatter.format(date));

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

Что форматирует API

API Intl.DateTimeFormat форматирует объекты Date в JavaScript. Объект Date представляет конкретный момент времени, включая дату, время и информацию о часовом поясе.

Когда вы форматируете объект Date, API преобразует его в строку по правилам выбранного языка. По умолчанию API форматирует только дату и не показывает время.

const formatter = new Intl.DateTimeFormat('en-US');

const dateWithTime = new Date('2025-03-15T14:30:00');
console.log(formatter.format(dateWithTime));
// Output: "3/15/2025"

Объект Date содержит информацию о времени, но стандартный форматтер её игнорирует. Позже мы разберём, как форматировать дату и время вместе или только время.

Создание дат для форматирования

Создать объект Date можно разными способами. Самый надёжный — использовать строки дат в формате ISO 8601.

const date1 = new Date('2025-03-15');
const date2 = new Date('2025-12-31');
const date3 = new Date('2025-01-01');

const formatter = new Intl.DateTimeFormat('en-US');

console.log(formatter.format(date1));
// Output: "3/15/2025"

console.log(formatter.format(date2));
// Output: "12/31/2025"

console.log(formatter.format(date3));
// Output: "1/1/2025"

Строки ISO 8601 используют формат YYYY-MM-DD. Этот формат однозначен и одинаково работает во всех языках и часовых поясах.

Форматирование дат из временных меток

Можно также создавать объекты Date из Unix-меток времени. Unix-метка — это количество миллисекунд с 1 января 1970 года по UTC.

const timestamp = 1710489600000; // March 15, 2025
const date = new Date(timestamp);

const formatter = new Intl.DateTimeFormat('en-US');
console.log(formatter.format(date));
// Output: "3/15/2025"

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

Вы также можете передать метку времени напрямую в метод format(), не создавая сначала объект Date.

const formatter = new Intl.DateTimeFormat('en-US');
const timestamp = 1710489600000;

console.log(formatter.format(timestamp));
// Output: "3/15/2025"

API принимает как объекты Date, так и метки времени. Используйте тот способ, который лучше подходит для вашего кода.

Форматирование текущей даты

Чтобы отформатировать текущую дату, создайте объект Date без аргументов. Это создаст объект Date, который будет представлять текущий момент.

const formatter = new Intl.DateTimeFormat('en-US');
const now = new Date();

console.log(formatter.format(now));
// Output: "10/15/2025" (or current date when run)

Вы также можете напрямую передать Date.now(), который вернёт текущую метку времени в виде числа.

const formatter = new Intl.DateTimeFormat('en-US');

console.log(formatter.format(Date.now()));
// Output: "10/15/2025" (or current date when run)

Оба способа дают одинаковый результат.

Повторное использование форматтеров для повышения производительности

Создание нового экземпляра Intl.DateTimeFormat включает загрузку данных локали и обработку опций. Если нужно форматировать несколько дат с одной локалью и настройками, создайте форматтер один раз и используйте его повторно.

const formatter = new Intl.DateTimeFormat('en-US');

const dates = [
  new Date('2025-01-01'),
  new Date('2025-06-15'),
  new Date('2025-12-31')
];

dates.forEach(date => {
  console.log(formatter.format(date));
});
// Output:
// "1/1/2025"
// "6/15/2025"
// "12/31/2025"

Этот способ эффективнее, чем создавать новый форматтер для каждой даты. Разница в производительности становится заметной при форматировании массивов из сотен или тысяч дат.

Форматирование дат в шаблонах

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

const formatter = new Intl.DateTimeFormat(navigator.language);

const publishedDate = new Date('2025-03-15');
const updatedDate = new Date('2025-04-20');

document.getElementById('published').textContent = formatter.format(publishedDate);
document.getElementById('updated').textContent = formatter.format(updatedDate);

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