是否有任何 JavaScript 标准 API 可以根据语言环境解析为数字?

2022-01-17 00:00:00 numbers parsing locale javascript

对于根据区域设置格式化数字,有一个标准的 JavaScript API:Intl.NumberFormat

For formatting a number according to locale, there is a standard JavaScript API: Intl.NumberFormat

但是对于反向操作,将字符串解析为数字我找不到任何支持语言环境的标准 API:

But for the reverse action, parsing a string to a number I cannot find any standard API supporting locales:

  • Number 不支持任何语言环境论据.
  • parseFloat 和 parseInt 也不支持任何语言环境参数.
  • Number does not support any locale arguments.
  • parseFloat and parseInt don't support any locale arguments either.

真的没有 JavaScript 标准 API 可以根据语言环境将字符串解析为数字吗?

Is there really no JavaScript standard API to parse a string to a number according to a locale?

如果没有:是否有任何市场成熟的开源库可以这样做?

And if not: are there any market established, open source libraries to do so?

推荐答案

NPM 包 d2l-intl 提供了一个区域敏感的解析器.

The NPM package d2l-intl provides a locale-sensitive parser.

const { NumberFormat, NumberParse } = require('d2l-intl');
const formatter = new NumberFormat('es');
const parser = new NumberParse('es');
const number = 1234.5;
console.log(formatter.format(number));                 // 1.234,5
console.log(parser.parse(formatter.format(1234.5)));   // 1234.5

不幸的是,该库仅支持 少数语言环境 开箱即用.它还使用仅支持西方阿拉伯数字的 parseInt,因此对于使用不同数字系统的语言环境,您将不得不变得更加聪明.这是一个解决方案 我通过 迈克·博斯托克.我不想因此而受到赞扬,但我在这里为后代复制了它(根据我自己的喜好进行了一些细微的调整):

Unfortunately, that library only comes with support for a handful of locales out of the box. It also uses parseInt which only supports Western Arabic numerals, so for locales that use different numeral systems, you're going to have to get more clever. Here's one solution I found by Mike Bostock. I don't want to take credit for it, but I've reproduced it here for posterity (with some slight tweaks based on my own preferences):

class NumberParser {
  constructor(locale) {
    const format = new Intl.NumberFormat(locale);
    const parts = format.formatToParts(12345.6);
    const numerals = Array.from({ length: 10 }).map((_, i) => format.format(i));
    const index = new Map(numerals.map((d, i) => [d, i]));
    this._group = new RegExp(`[${parts.find(d => d.type === "group").value}]`, "g");
    this._decimal = new RegExp(`[${parts.find(d => d.type === "decimal").value}]`);
    this._numeral = new RegExp(`[${numerals.join("")}]`, "g");
    this._index = d => index.get(d);
  }
  parse(string) {
    return (string = string.trim()
      .replace(this._group, "")
      .replace(this._decimal, ".")
      .replace(this._numeral, this._index)) ? +string : NaN;
  }
}

const formatter = new Intl.NumberFormat('ar-EG');
const parser = new NumberParser('ar-EG');
console.log(formatter.format(1234.5));               // ١٬٢٣٤٫٥
console.log(parser.parse(formatter.format(1234.5))); // 1234.5

相关文章