Перейти к основному содержимому

`Intl.NumberFormat`

· 4 мин. чтения
Маттиас Байненс ([@mathias](https://twitter.com/mathias)) и Шейн Ф. Карр

Вы, возможно, уже знакомы с API Intl.NumberFormat, так как его поддержка существует в современных средах уже некоторое время.

В своей самой базовой форме Intl.NumberFormat позволяет создавать экземпляр форматтера, поддерживающий форматирование чисел с учетом локали. Так же, как и другие API Intl.*Format, экземпляр форматтера поддерживает методы format и formatToParts:

const formatter = new Intl.NumberFormat('en');
formatter.format(987654.321);
// → '987,654.321'
formatter.formatToParts(987654.321);
// → [
// → { type: 'integer', value: '987' },
// → { type: 'group', value: ',' },
// → { type: 'integer', value: '654' },
// → { type: 'decimal', value: '.' },
// → { type: 'fraction', value: '321' }
// → ]

Замечание: Хотя многие функции Intl.NumberFormat можно реализовать с помощью Number.prototype.toLocaleString, Intl.NumberFormat часто предпочтительнее, так как позволяет создавать многоразовый экземпляр форматтера, что, как правило, более эффективно.

Совсем недавно API Intl.NumberFormat получил новые возможности.

Поддержка BigInt

Помимо Number, Intl.NumberFormat теперь может форматировать и BigInt:

const formatter = new Intl.NumberFormat('fr');
formatter.format(12345678901234567890n);
// → '12 345 678 901 234 567 890'
formatter.formatToParts(123456n);
// → [
// → { type: 'integer', value: '123' },
// → { type: 'group', value: ' ' },
// → { type: 'integer', value: '456' }
// → ]

Единицы измерения

Intl.NumberFormat в настоящее время поддерживает следующие так называемые простые единицы:

  • угол: degree
  • площадь: acre, hectare
  • концентрация: percent
  • цифровые: bit, byte, kilobit, kilobyte, megabit, megabyte, gigabit, gigabyte, terabit, terabyte, petabyte
  • длительность: millisecond, second, minute, hour, day, week, month, year
  • длина: millimeter, centimeter, meter, kilometer, inch, foot, yard, mile, mile-scandinavian
  • масса: gram, kilogram, ounce, pound, stone
  • температура: celsius, fahrenheit
  • объем: liter, milliliter, gallon, fluid-ounce

Чтобы форматировать числа с локализованными единицами, используйте параметры style и unit:

const formatter = new Intl.NumberFormat('en', {
style: 'unit',
unit: 'kilobyte',
});
formatter.format(1.234);
// → '1.234 kB'
formatter.format(123.4);
// → '123.4 kB'

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

Простые единицы можно сочетать в произвольные сочетания числителя и знаменателя для выражения составных единиц, таких как "литры на акр" или "метры в секунду":

const formatter = new Intl.NumberFormat('en', {
style: 'unit',
unit: 'meter-per-second',
});
formatter.format(299792458);
// → '299,792,458 m/s'

Компактное, научное и инженерное представление

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

{
// Тест стандартного представления.
const formatter = new Intl.NumberFormat('en', {
notation: 'standard', // Это подразумеваемое значение по умолчанию.
});
formatter.format(1234.56);
// → '1,234.56'
formatter.format(123456);
// → '123,456'
formatter.format(123456789);
// → '123,456,789'
}

{
// Тест компактного представления.
const formatter = new Intl.NumberFormat('en', {
notation: 'compact',
});
formatter.format(1234.56);
// → '1.2K'
formatter.format(123456);
// → '123K'
formatter.format(123456789);
// → '123M'
}
примечание

Замечание: По умолчанию компактное представление округляет до ближайшего целого числа, но всегда сохраняет 2 значащие цифры. Вы можете задать любые комбинации {minimum,maximum}FractionDigits или {minimum,maximum}SignificantDigits, чтобы переопределить это поведение.

Intl.NumberFormat также может форматировать числа в научной нотации:

const formatter = new Intl.NumberFormat('en', {
style: 'unit',
unit: 'meter-per-second',
notation: 'scientific',
});
formatter.format(299792458);
// → '2.998E8 m/s'

Инженерная нотация также поддерживается:

const formatter = new Intl.NumberFormat('en', {
style: 'unit',
unit: 'meter-per-second',
notation: 'engineering',
});
formatter.format(299792458);
// → '299.792E6 m/s'

Отображение знака

В некоторых ситуациях (например, при представлении дельт) полезно явно отображать знак, даже когда число положительное. Новый параметр signDisplay позволяет это сделать:

const formatter = new Intl.NumberFormat('en', {
style: 'unit',
unit: 'percent',
signDisplay: 'always',
});
formatter.format(-12.34);
// → '-12.34%'
formatter.format(12.34);
// → '+12.34%'
formatter.format(0);
// → '+0%'
formatter.format(-0);
// → '-0%'

Чтобы избежать отображения знака, если значение равно 0, используйте signDisplay: 'exceptZero':

const formatter = new Intl.NumberFormat('en', {
style: 'unit',
unit: 'percent',
signDisplay: 'exceptZero',
});
formatter.format(-12.34);
// → '-12.34%'
formatter.format(12.34);
// → '+12.34%'
formatter.format(0);
// → '0%'
// Примечание: -0 все еще отображается со знаком, как и ожидалось:
formatter.format(-0);
// → '-0%'

Для валют параметр currencySign позволяет использовать учетный формат, который активирует формат, зависящий от локали, для отрицательных сумм; например, оборачивание суммы в скобки:

const formatter = new Intl.NumberFormat('en', {
style: 'currency',
currency: 'USD',
signDisplay: 'exceptZero',
currencySign: 'accounting',
});
formatter.format(-12.34);
// → '($12.34)'
formatter.format(12.34);
// → '+$12.34'
formatter.format(0);
// → '$0.00'
formatter.format(-0);
// → '($0.00)'

Дополнительная информация

Соответствующее предложение спецификации содержит больше информации и примеров, включая руководство по обнаружению наличия каждой функции в Intl.NumberFormat.