Intl.DateTimeFormat

Объект для форматирования даты и времени с учётом локали

Время чтения: 7 мин

Кратко

Скопировано

Intl.DateTimeFormat — объект, содержащий функции форматирования даты и времени с учётом локали.

Конструктор объекта Intl.DateTimeFormat принимает следующие параметры:

  1. locales код или массив идентификаторов локалей. Элементы этого массива могут обозначать язык, например en, или язык и регион, например en-US и также дополнительные обозначения, например zh-Hans-CN – китайский язык, упрощённый китайский скрипт и регион Китай.
  2. options дополнительные опции.

Как понять

Скопировано

Форматирование объекта Date — настоящая головная боль. Чтобы красиво отображать дату и время не обязательно подключать тяжеловесные сторонние библиотеки. Можно воспользоваться встроенным объектом Intl.DateTimeFormat.

Этот способ форматирования поддерживается всеми современными браузерами.

Пример

Скопировано

Чтобы отобразить дату несколькими, способами создадим объект даты при помощи статического метода Date.UTC(). Этот метод возвращает количество миллисекунд с момента начала unix-эпохи. Date.UTC() работает с всемирным координатным временем (UTC)

        
          
          const date = new Date(Date.UTC(2020, 11, 20, 3, 23, 16, 738));
          
const date = new Date(Date.UTC(2020, 11, 20, 3, 23, 16, 738));

        
        
          
        
      

Стандартное форматирование, в зависимости от локали:

        
          
          console.log(new Intl.DateTimeFormat('en-US').format(date));// "12/20/2020"
          console.log(new Intl.DateTimeFormat('en-US').format(date));
// "12/20/2020"

        
        
          
        
      
        
          
          console.log(new Intl.DateTimeFormat("ru", {  weekday: "short",  year: "2-digit",  month: "long",  day: "numeric"}).format(date))// вс, 20 декабря 20 г.
          console.log(new Intl.DateTimeFormat("ru", {
  weekday: "short",
  year: "2-digit",
  month: "long",
  day: "numeric"}).format(date))
// вс, 20 декабря 20 г.

        
        
          
        
      

Укажем формат даты и времени, используя параметр style (full, long, medium, short):

        
          
          console.log(new Intl.DateTimeFormat('en-GB', { dateStyle: 'full', timeStyle: 'long', timeZone: 'Australia/Sydney' }).format(date));// "Sunday, 20 December 2020 at 14:23:16 GMT+11"
          console.log(new Intl.DateTimeFormat('en-GB', { dateStyle: 'full', timeStyle: 'long', timeZone: 'Australia/Sydney' }).format(date));
// "Sunday, 20 December 2020 at 14:23:16 GMT+11"

        
        
          
        
      

Как пишется

Скопировано
        
          
          // создание экземпляраconst formattedDate = new Intl.DateTimeFormat('ru').format(date);
          // создание экземпляра
const formattedDate = new Intl.DateTimeFormat('ru').format(date);

        
        
          
        
      

Опции

Скопировано
  • timeZone — значение часового пояса: UTC, America/New_York, Europe/Paris и т.д.
  • calendar — значение выбранного календаря: chinese, gregory, indian и т.д.
  • numberingSystem — используемая система счисления: arab, beng, latin и т.д.
  • localeMatcher — алгоритм для согласования выбранной локали:
    • lookup — поиск следует алгоритму поиска, определённому в BCP 47,
    • best fit — (наилучший подходящий) позволяет среде выполнения выбрать локаль.
  • formatMatcher алгоритм для форматирования: basic, best fit.
  • hour12 если имеет значение true, используется 12-часовой формат.
  • hourCycle часовой формат: h11, h12, h23, h24.
  • dateStyle стиль форматирования даты: full, long, medium, short.
  • weekday день недели: long, short, narrow.
  • day день месяца: numeric, 2-digit.
  • month месяц: numeric, 2-digit, long, short, narrow.
  • year год: numeric, 2-digit.
  • era эпоха: long, short, narrow.
  • timeStyle стиль форматирования времени: full, long, medium, short.
  • hour часы: numeric, 2-digit.
  • minute минуты: numeric, 2-digit.
  • second секунды: numeric, 2-digit.
  • dayPeriod часть дня (утро, вечер и т.п.): narrow, short, long.
  • timeZoneName название часового пояса (UTC, PTC): long, short.

Методы

Скопировано

Intl.DateTimeFormat.format() — геттер, который форматирует дату, в соответствии с языковым стандартом и параметрами форматирования этого объекта DateTimeFormat. Возвращает текущую дату в кратком виде (dateStyle: short) в виде строки.

        
          
          const date = Date.now();const formatter = new Intl.DateTimeFormat('ru', {  weekday: 'long',  year: 'numeric',  month: 'numeric',  day: 'numeric',  hour: 'numeric',  minute: 'numeric',  second: 'numeric',  hour12: true,  timeZone: 'UTC'});formatter.format(date);// суббота, 27.05.2023 г., 10:55:18 PM
          const date = Date.now();

const formatter = new Intl.DateTimeFormat('ru', {
  weekday: 'long',
  year: 'numeric',
  month: 'numeric',
  day: 'numeric',
  hour: 'numeric',
  minute: 'numeric',
  second: 'numeric',
  hour12: true,
  timeZone: 'UTC'
});

formatter.format(date);
// суббота, 27.05.2023 г., 10:55:18 PM

        
        
          
        
      

Intl.DateTimeFormat.formatToParts() — форматирует передаваемую строку по частям с учётом DateTimeFormat. Возвращает массив объектов, представляющих строку даты в частях, которые можно использовать для настраиваемого форматирования с учётом локали.

        
          
          formatter.formatToParts(date);
          formatter.formatToParts(date);

        
        
          
        
      

В консоли мы получим следующее:

        
          
          [  {type: 'weekday', value: 'суббота'},  {type: 'literal', value: ', '},  {type: 'day', value: '27'},  {type: 'literal', value: '.'},  {type: 'month', value: '05'},  {type: 'literal', value: '.'},  {type: 'year', value: '2023'},  {type: 'literal', value: ' г., '},  {type: 'hour', value: '10'},  {type: 'literal', value: ':'},  {type: 'minute', value: '55'},  {type: 'literal', value: ':'},  {type: 'second', value: '18'},  {type: 'literal', value: ' '},  {type: 'dayPeriod', value: 'PM'}]
          [
  {type: 'weekday', value: 'суббота'},
  {type: 'literal', value: ', '},
  {type: 'day', value: '27'},
  {type: 'literal', value: '.'},
  {type: 'month', value: '05'},
  {type: 'literal', value: '.'},
  {type: 'year', value: '2023'},
  {type: 'literal', value: ' г., '},
  {type: 'hour', value: '10'},
  {type: 'literal', value: ':'},
  {type: 'minute', value: '55'},
  {type: 'literal', value: ':'},
  {type: 'second', value: '18'},
  {type: 'literal', value: ' '},
  {type: 'dayPeriod', value: 'PM'}
]

        
        
          
        
      

Intl.DateTimeFormat.prototype.resolvedOptions() — возвращает новый объект со свойствами, отражающими локаль и параметры форматирования, которые вычислены при инициализации объекта.

        
          
          {  calendar: "gregory",  day: "2-digit",  hour: "numeric",  hour12: true,  hourCycle: "h11",  locale: "ru",  minute: "2-digit",  month: "2-digit",  numberingSystem: "latn",  second: "2-digit",  timeZone: "UTC",  weekday: "long",  year: "numeric"}
          {
  calendar: "gregory",
  day: "2-digit",
  hour: "numeric",
  hour12: true,
  hourCycle: "h11",
  locale: "ru",
  minute: "2-digit",
  month: "2-digit",
  numberingSystem: "latn",
  second: "2-digit",
  timeZone: "UTC",
  weekday: "long",
  year: "numeric"
}

        
        
          
        
      

Intl.DateTimeFormat.prototype.formatRange()
получает две даты и форматирует диапазон дат наиболее кратким образом на основе языкового стандарта и параметров, предоставленных при создании экземпляра DateTimeFormat.

        
          
          const date1 = new Date(Date.UTC(2018, 0, 10, 10, 0, 0));const currentDate = Date.now();const fmt1 = new Intl.DateTimeFormat("en", {  year: "2-digit",  month: "numeric",  day: "numeric",  hour: "numeric",  minute: "numeric",});console.log(fmt1.formatRange(date1, currentDate));// 1/10/18, 1:00 PM – 5/28/23, 2:08 AM
          const date1 = new Date(Date.UTC(2018, 0, 10, 10, 0, 0));
const currentDate = Date.now();

const fmt1 = new Intl.DateTimeFormat("en", {
  year: "2-digit",
  month: "numeric",
  day: "numeric",
  hour: "numeric",
  minute: "numeric",
});

console.log(fmt1.formatRange(date1, currentDate));
// 1/10/18, 1:00 PM – 5/28/23, 2:08 AM

        
        
          
        
      

Intl.DateTimeFormat.prototype.formatRangeToParts()
получает две даты и возвращает массив объектов, содержащих токены, зависящие от языкового стандарта, представляющие каждую часть отформатированного диапазона дат. Возвращает формат, аналогичный formatToParts(date).

        
          
          const date1 = new Date(Date.UTC(2018, 0, 10, 10, 0, 0));const currentDate = Date.now();const dateTimeFormat = new Intl.DateTimeFormat('en', {  hour: 'numeric',  minute: 'numeric'});const parts = dateTimeFormat.formatRangeToParts(date1, currentDate);for (const part of parts) {  console.log(part);}
          const date1 = new Date(Date.UTC(2018, 0, 10, 10, 0, 0));
const currentDate = Date.now();

const dateTimeFormat = new Intl.DateTimeFormat('en', {
  hour: 'numeric',
  minute: 'numeric'
});

const parts = dateTimeFormat.formatRangeToParts(date1, currentDate);
for (const part of parts) {
  console.log(part);
}

        
        
          
        
      

В консоли мы получим следующее:

        
          
          [  {type: 'month', value: '1', source: 'startRange'},  {type: 'literal', value: '/', source: 'startRange'},  {type: 'day', value: '10', source: 'startRange'},  {type: 'literal', value: '/', source: 'startRange'},  {type: 'year', value: '2018', source: 'startRange'},  {type: 'literal', value: ', ', source: 'startRange'},  {type: 'hour', value: '1', source: 'startRange'},  {type: 'literal', value: ':', source: 'startRange'},  {type: 'minute', value: '00', source: 'startRange'},  {type: 'literal', value: ' ', source: 'startRange'},  {type: 'dayPeriod', value: 'PM', source: 'startRange'},  {type: 'literal', value: ' – ', source: 'shared'},  {type: 'month', value: '5', source: 'endRange'},  {type: 'literal', value: '/', source: 'endRange'},  {type: 'day', value: '29', source: 'endRange'},  {type: 'literal', value: '/', source: 'endRange'},  {type: 'year', value: '2023', source: 'endRange'},  {type: 'literal', value: ', ', source: 'endRange'},  {type: 'hour', value: '12', source: 'endRange'},  {type: 'literal', value: ':', source: 'endRange'},  {type: 'minute', value: '41', source: 'endRange'},  {type: 'literal', value: ' ', source: 'endRange'},  {type: 'dayPeriod', value: 'PM', source: 'endRange'}]
          [
  {type: 'month', value: '1', source: 'startRange'},
  {type: 'literal', value: '/', source: 'startRange'},
  {type: 'day', value: '10', source: 'startRange'},
  {type: 'literal', value: '/', source: 'startRange'},
  {type: 'year', value: '2018', source: 'startRange'},
  {type: 'literal', value: ', ', source: 'startRange'},
  {type: 'hour', value: '1', source: 'startRange'},
  {type: 'literal', value: ':', source: 'startRange'},
  {type: 'minute', value: '00', source: 'startRange'},
  {type: 'literal', value: ' ', source: 'startRange'},
  {type: 'dayPeriod', value: 'PM', source: 'startRange'},
  {type: 'literal', value: ' – ', source: 'shared'},
  {type: 'month', value: '5', source: 'endRange'},
  {type: 'literal', value: '/', source: 'endRange'},
  {type: 'day', value: '29', source: 'endRange'},
  {type: 'literal', value: '/', source: 'endRange'},
  {type: 'year', value: '2023', source: 'endRange'},
  {type: 'literal', value: ', ', source: 'endRange'},
  {type: 'hour', value: '12', source: 'endRange'},
  {type: 'literal', value: ':', source: 'endRange'},
  {type: 'minute', value: '41', source: 'endRange'},
  {type: 'literal', value: ' ', source: 'endRange'},
  {type: 'dayPeriod', value: 'PM', source: 'endRange'}
]

        
        
          
        
      

Преобразование в ISO формат

Скопировано

У объекта Date есть метод toISOString(), который возвращает строку в расширенном ISO формате - YYYY-MM-DDTHH:mm:ss.sssZ. Часовой пояс всегда равен UTC, что обозначено суффиксом "Z".

Но Intl.DateTimeFormat не позволяет выбрать в качестве формата iso8601. Код, приведённый ниже, упадёт с ошибкой:

        
          
          const date = new Date();const options = {  year: 'numeric',  month: 'numeric',  day: 'numeric'};const isoDate = new Intl.DateTimeFormat(['iso8601'], options).format(date);// Uncaught RangeError: Incorrect locale information provided at new DateTimeFormat...
          const date = new Date();
const options = {
  year: 'numeric',
  month: 'numeric',
  day: 'numeric'
};
const isoDate = new Intl.DateTimeFormat(['iso8601'], options).format(date);

// Uncaught RangeError: Incorrect locale information provided at new DateTimeFormat...

        
        
          
        
      

Почему возникает такая ошибка?

Дело в том, что Intl работает только с локалью. Так как в формате ISO-8601 нет никакой локали, то и отформатировать его не получится.

Однако можно вручную преобразовать дату в формат, совместимый с ISO-8601:

        
          
          const date = new Date();const dateOptions = {  year: 'numeric',  month: 'numeric',  day: 'numeric',};const formattedDate = new Intl.DateTimeFormat('en-ca', dateOptions).format(date);const timeOptions = {  hour: 'numeric',  minute: 'numeric',  second: 'numeric',  hourCycle: 'h24',}const formattedTime = new Intl.DateTimeFormat('en-ca', timeOptions).format(date);const dateTime = `${formattedDate}T${formattedTime}Z`;// '2023-05-29T15:00:00Z'
          const date = new Date();
const dateOptions = {
  year: 'numeric',
  month: 'numeric',
  day: 'numeric',
};
const formattedDate = new Intl.DateTimeFormat('en-ca', dateOptions).format(date);

const timeOptions = {
  hour: 'numeric',
  minute: 'numeric',
  second: 'numeric',
  hourCycle: 'h24',
}
const formattedTime = new Intl.DateTimeFormat('en-ca', timeOptions).format(date);
const dateTime = `${formattedDate}T${formattedTime}Z`;
// '2023-05-29T15:00:00Z'