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

Используйте 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));
// Вывод: "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));
// Вывод: "3/15/2025"

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

const deFormatter = new Intl.DateTimeFormat('de-DE');
console.log(deFormatter.format(date));
// Вывод: "15.3.2025"

const jpFormatter = new Intl.DateTimeFormat('ja-JP');
console.log(jpFormatter.format(date));
// Вывод: "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));
// Вывод зависит от локали пользователя
// Для en-US: "3/15/2025"
// Для en-GB: "15/03/2025"
// Для de-DE: "15.3.2025"
// Для 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

Intl.DateTimeFormat API форматирует объекты 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));
// Вывод: "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));
// Вывод: "3/15/2025"

console.log(formatter.format(date2));
// Вывод: "12/31/2025"

console.log(formatter.format(date3));
// Вывод: "1/1/2025"

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

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

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

const timestamp = 1710489600000; // 15 марта 2025 года
const date = new Date(timestamp);

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

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

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

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

console.log(formatter.format(timestamp));
// Вывод: "3/15/2025"

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

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

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

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

console.log(formatter.format(now));
// Вывод: "10/15/2025" (или текущая дата при выполнении)

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

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

console.log(formatter.format(Date.now()));
// Вывод: "10/15/2025" (или текущая дата при выполнении)

Оба подхода дают идентичные результаты.

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

Создание нового экземпляра 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));
});
// Вывод:
// "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);

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