Pular para o conteúdo principal

`Intl.NumberFormat`

· Leitura de 4 minutos
Mathias Bynens ([@mathias](https://twitter.com/mathias)) e Shane F. Carr

Você pode já estar familiarizado com a API Intl.NumberFormat, já que tem sido suportada em ambientes modernos há algum tempo.

Na sua forma mais básica, Intl.NumberFormat permite criar uma instância de formatador reutilizável que suporta formatação de números sensível ao local. Assim como outras APIs Intl.*Format, uma instância de formatador suporta tanto o método format quanto o método 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' }
// → ]

Nota: Embora muito da funcionalidade do Intl.NumberFormat possa ser alcançada utilizando Number.prototype.toLocaleString, Intl.NumberFormat geralmente é a melhor escolha, pois permite criar uma instância de formatador reutilizável que tende a ser mais eficiente.

Recentemente, a API Intl.NumberFormat ganhou algumas novas funcionalidades.

Suporte a BigInt

Além de Numbers, Intl.NumberFormat agora também pode formatar BigInts:

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' }
// → ]

Unidades de medida

Intl.NumberFormat atualmente suporta as seguintes chamadas unidades simples:

  • ângulo: degree
  • área: acre, hectare
  • concentração: percent
  • digital: bit, byte, kilobit, kilobyte, megabit, megabyte, gigabit, gigabyte, terabit, terabyte, petabyte
  • duração: millisecond, second, minute, hour, day, week, month, year
  • comprimento: millimeter, centimeter, meter, kilometer, inch, foot, yard, mile, mile-scandinavian
  • massa: gram, kilogram, ounce, pound, stone
  • temperatura: celsius, fahrenheit
  • volume: liter, milliliter, gallon, fluid-ounce

Para formatar números com unidades localizadas, use as opções style e 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'

Observe que, ao longo do tempo, mais unidades podem ser adicionadas. Consulte a especificação para a lista mais atualizada.

As unidades simples acima podem ser combinadas em pares arbitrários de numerador e denominador para expressar unidades compostas, como “litros por acre” ou “metros por segundo”:

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

Notação compacta, científica e de engenharia

Notação compacta utiliza símbolos específicos do local para representar números grandes. É uma alternativa mais amigável para humanos em relação à notação científica:

{
// Teste de notação padrão.
const formatter = new Intl.NumberFormat('en', {
notation: 'standard', // Este é o padrão implícito.
});
formatter.format(1234.56);
// → '1,234.56'
formatter.format(123456);
// → '123,456'
formatter.format(123456789);
// → '123,456,789'
}

{
// Teste de notação compacta.
const formatter = new Intl.NumberFormat('en', {
notation: 'compact',
});
formatter.format(1234.56);
// → '1.2K'
formatter.format(123456);
// → '123K'
formatter.format(123456789);
// → '123M'
}
nota

Nota: Por padrão, a notação compacta arredonda para o número inteiro mais próximo, mas sempre mantém 2 dígitos significativos. Você pode definir qualquer um de {minimum,maximum}FractionDigits ou {minimum,maximum}SignificantDigits para substituir esse comportamento.

Intl.NumberFormat também pode formatar números em notação científica:

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

Notação de engenharia também é suportada:

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

Exibição de sinal

Em certas situações (como apresentar deltas), é útil exibir explicitamente o sinal, mesmo quando o número é positivo. A nova opção signDisplay permite isso:

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%'

Para evitar mostrar o sinal quando o valor for 0, use 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%'
// Nota: -0 ainda exibe um sinal, como esperado:
formatter.format(-0);
// → '-0%'

Para moeda, a opção currencySign permite o formato de contabilidade, que habilita um formato específico de localidade para valores de moeda negativos; por exemplo, envolvendo o valor entre parênteses:

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)'

Mais informações

A proposta da especificação relevante tem mais informações e exemplos, incluindo orientações sobre como detectar funcionalidade de cada recurso individual de Intl.NumberFormat.