Стили отображения времени

В Intl.DateTimeFormat форматирование времени определяется набором параметров, которые управляют тем, какие компоненты времени отображаются и в каком виде. Современный API предоставляет как детальную настройку (часы, минуты, секунды), так и высокоуровневые стили через timeStyle, которые делегируют выбор формата локали.


Базовые компоненты времени

Формирование строки времени в Intl.DateTimeFormat опирается на следующие поля:

  • hour — часы
  • minute — минуты
  • second — секунды
  • fractionalSecondDigits — доли секунды
  • timeZoneName — отображение часового пояса
const formatter = new Intl.DateTimeFormat('ru-RU', {
  hour: '2-digit',
  minute: '2-digit',
  second: '2-digit'
});

console.log(formatter.format(new Date()));

Такой подход даёт точный контроль над тем, какие части времени будут включены в результат.


12-часовой и 24-часовой формат

Отображение времени зависит от параметра hour12, который управляет системой часов:

  • true — 12-часовой формат (AM/PM)
  • false — 24-часовой формат
  • undefined — выбор по умолчанию для локали
const fmt12 = new Intl.DateTimeFormat('en-US', {
  hour: 'numeric',
  minute: 'numeric',
  hour12: true
});

const fmt24 = new Intl.DateTimeFormat('ru-RU', {
  hour: 'numeric',
  minute: 'numeric',
  hour12: false
});

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


Высокоуровневые стили времени: timeStyle

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

Поддерживаемые значения:

  • full — максимально подробное отображение
  • long — расширенный формат
  • medium — стандартный формат
  • short — краткий формат
const full = new Intl.DateTimeFormat('ru-RU', {
  timeStyle: 'full'
});

const short = new Intl.DateTimeFormat('ru-RU', {
  timeStyle: 'short'
});

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


Взаимодействие timeStyle с другими параметрами

timeStyle нельзя комбинировать с низкоуровневыми компонентами времени (hour, minute, second). Попытка совместного использования приводит к ошибке.

// Некорректно
new Intl.DateTimeFormat('ru-RU', {
  timeStyle: 'short',
  hour: '2-digit'
});

Правильный подход — выбрать один уровень абстракции:

  • либо высокоуровневый стиль (timeStyle)
  • либо ручная конфигурация полей

Секунды и доли секунды

Для отображения секунд используется поле second, а для более точного времени — fractionalSecondDigits.

const fmt = new Intl.DateTimeFormat('ru-RU', {
  hour: '2-digit',
  minute: '2-digit',
  second: '2-digit',
  fractionalSecondDigits: 3
});

Значение fractionalSecondDigits может быть:

  • 1 — десятые доли
  • 2 — сотые
  • 3 — миллисекунды

Отображение часового пояса

Часовой пояс управляется через timeZoneName:

const fmt = new Intl.DateTimeFormat('ru-RU', {
  hour: '2-digit',
  minute: '2-digit',
  timeZoneName: 'short'
});

Возможные значения:

  • short — сокращённое обозначение
  • long — полное название

Отображение зависит от локали и системных данных.


Локаль как источник стиля времени

Локаль влияет на:

  • порядок компонентов времени
  • разделители (двоеточие, точка)
  • наличие ведущих нулей
  • использование AM/PM
  • формат часового пояса
console.log(new Intl.DateTimeFormat('en-US', {
  hour: 'numeric',
  minute: 'numeric'
}).format(new Date()));

console.log(new Intl.DateTimeFormat('de-DE', {
  hour: 'numeric',
  minute: 'numeric'
}).format(new Date()));

Один и тот же объект Date может отображаться совершенно по-разному.


hourCycle и различия с hour12

Параметр hourCycle предоставляет более точное управление циклом часов:

  • h11 — 0–11, без AM/PM
  • h12 — 1–12, с AM/PM
  • h23 — 0–23
  • h24 — 1–24
const fmt = new Intl.DateTimeFormat('en-GB', {
  hour: 'numeric',
  minute: 'numeric',
  hourCycle: 'h23'
});

hourCycle имеет приоритет над hour12, если они используются вместе.


Поведение short / medium / long / full

Хотя timeStyle выглядит простым, его поведение зависит от внутренней таблицы CLDR (Common Locale Data Repository). Это означает:

  • формат не фиксирован в стандарте JavaScript
  • он может изменяться между окружениями
  • результат зависит от версии ICU

Пример различий:

  • short может показывать 14:05
  • medium может добавлять секунды 14:05:33
  • long может добавлять часовой пояс
  • full может включать полное локализованное представление времени

Совмещение времени и даты

Хотя тема относится к времени, важно учитывать взаимодействие с dateStyle:

new Intl.DateTimeFormat('ru-RU', {
  dateStyle: 'long',
  timeStyle: 'short'
});

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


Типичные сценарии использования стилей времени

Интерфейсы приложений

Краткие форматы:

new Intl.DateTimeFormat('ru-RU', {
  timeStyle: 'short'
});

Используются в списках сообщений, уведомлениях, чатах.


Логи и технические данные

Точные значения:

new Intl.DateTimeFormat('ru-RU', {
  hour: '2-digit',
  minute: '2-digit',
  second: '2-digit',
  fractionalSecondDigits: 3
});

Применяется в логировании и отладке.


Пользовательские настройки локали

Формат, зависящий от региона:

new Intl.DateTimeFormat(undefined, {
  timeStyle: 'medium'
});

Позволяет автоматически адаптироваться под системную локаль пользователя.


Особенности реализации в браузерах и Node.js

Поведение Intl.DateTimeFormat зависит от:

  • версии ICU
  • операционной системы
  • движка (V8, SpiderMonkey, JavaScriptCore)

Это влияет на:

  • точность времени
  • доступные локали
  • поддержку timeStyle

Ограничения и нюансы

  • не все старые окружения поддерживают timeStyle
  • комбинация параметров строго ограничена
  • форматирование не гарантирует стабильную строку между версиями движка
  • локали могут давать неожиданные визуальные различия

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

Создание форматтера дорого по сравнению с его использованием. Оптимальная практика:

  • создавать один экземпляр Intl.DateTimeFormat
  • переиспользовать его
const fmt = new Intl.DateTimeFormat('ru-RU', {
  timeStyle: 'short'
});

function render(time) {
  return fmt.format(time);
}