Get List of Supported Currencies

后端 未结 2 1369
后悔当初
后悔当初 2020-12-21 00:19

Other than just guessing (like I\'ve done below), is there a more direct and efficient way of reflectively retrieving a list of all currencies supported by

相关标签:
2条回答
  • 2020-12-21 00:56

    You could load a known list via this XML:

    https://www.currency-iso.org/dam/downloads/lists/list_one.xml

    The list was found here: https://www.currency-iso.org/en/home/tables/table-a1.html

    <ISO_4217 Pblshd="2018-08-29">
      <CcyTbl>
        <CcyNtry>
          <CtryNm>
            UNITED KINGDOM OF GREAT BRITAIN AND NORTHERN IRELAND (THE)
          </CtryNm>
          <CcyNm>Pound Sterling</CcyNm>
          <Ccy>GBP</Ccy>
          <CcyNbr>826</CcyNbr>
          <CcyMnrUnts>2</CcyMnrUnts>
        </CcyNtry>
        <CcyNtry>
          <CtryNm>UNITED STATES OF AMERICA (THE)</CtryNm>
          <CcyNm>US Dollar</CcyNm>
          <Ccy>USD</Ccy>
          <CcyNbr>840</CcyNbr>
          <CcyMnrUnts>2</CcyMnrUnts>
        </CcyNtry>
      </CcyTbl>
    </ISO_4217>
    

    var xmlString = getSampleCurrencyXml();
    var xmlData = (new window.DOMParser()).parseFromString(xmlString, "text/xml");
    var knownCodes = [].slice.call(xmlData.querySelectorAll('Ccy')).map(n => n.textContent)
    
    // Fetch the XML instead?
    fetch('https://www.currency-iso.org/dam/downloads/lists/list_one.xml', { cache: 'default' })
      .then(response => response.text())
      .then(xmlStr => (new window.DOMParser()).parseFromString(xmlStr, "text/xml"))
      .then(data => knownCodes = data); // This may not work in the Stack Snippet
    
    console.log(getSupportedCurrencies().map(c => c.code + '\t' + c.name).join('\n'));
    
    function getSupportedCurrencies() {
      function $(amount, currency) {
        return Intl.NumberFormat('en-US', {
          style: 'currency',
          currency: currency,
          currencyDisplay: 'name'
        }).format(amount);
      }
      return knownCodes.reduce((currencies, cur) => {
        return (output => {
          return output.replace(/^[^ ]+ /, '') !== cur ?
            currencies.concat({
              code: cur,
              name: output.match(/(?<= ).+/)[0]
            }) :
            currencies;
        })($(0, cur).trim());
      }, []);
    }
    
    function getSampleCurrencyXml() {
      return `
        <ISO_4217 Pblshd="2018-08-29">
          <CcyTbl>
            <CcyNtry>
              <CtryNm>
                UNITED KINGDOM OF GREAT BRITAIN AND NORTHERN IRELAND (THE)
              </CtryNm>
              <CcyNm>Pound Sterling</CcyNm>
              <Ccy>GBP</Ccy>
              <CcyNbr>826</CcyNbr>
              <CcyMnrUnts>2</CcyMnrUnts>
            </CcyNtry>
            <CcyNtry>
              <CtryNm>UNITED STATES OF AMERICA (THE)</CtryNm>
              <CcyNm>US Dollar</CcyNm>
              <Ccy>USD</Ccy>
              <CcyNbr>840</CcyNbr>
              <CcyMnrUnts>2</CcyMnrUnts>
            </CcyNtry>
          </CcyTbl>
        </ISO_4217>
      `;
    }
    .as-console-wrapper { top: 0; max-height: 100% !important; }


    If you want to generate the codes still, you can use a product iterable.

    The following is based on Python's itertools.product function.

    let ary = product('ABCDEFGHIJKLMNOPQRSTUVWXYZ'.split(''), 3).map(a => a.join(''));
    
    function product(iterables, repeat) {
      var argv = Array.prototype.slice.call(arguments), argc = argv.length;
      if (argc === 2 && !isNaN(argv[argc - 1])) {
        var copies = [];
        for (var i = 0; i < argv[argc - 1]; i++) { copies.push(argv[0].slice()); }
        argv = copies;
      }
      return argv.reduce((accumulator, value) => {
        var tmp = [];
        accumulator.forEach(a0 => value.forEach(a1 => tmp.push(a0.concat(a1))));
        return tmp;
      }, [[]]);
    }
    

    Demo

    console.log(getSupportedCurrencies().map(c => c.code + '\t' + c.name).join('\n'));
    
    function getSupportedCurrencies() {
      function $(amount, currency) {
        return Intl.NumberFormat('en-US', {
          style: 'currency',
          currency: currency,
          currencyDisplay: 'name'
        }).format(amount);
      }
      let ary = product('ABCDEFGHIJKLMNOPQRSTUVWXYZ'.split(''), 3).map(a => a.join(''));
      return ary.reduce((currencies, cur) => {
        return (output => {
          return output.replace(/^[^ ]+ /, '') !== cur
            ? currencies.concat({ code : cur, name : output.match(/(?<= ).+/)[0] })
            : currencies;
        })($(0, cur).trim());
      }, []);
    }
    
    function product(iterables, repeat) {
      var argv = Array.prototype.slice.call(arguments), argc = argv.length;
      if (argc === 2 && !isNaN(argv[argc - 1])) {
        var copies = [];
        for (var i = 0; i < argv[argc - 1]; i++) { copies.push(argv[0].slice()); }
        argv = copies;
      }
      return argv.reduce((accumulator, value) => {
        var tmp = [];
        accumulator.forEach(a0 => value.forEach(a1 => tmp.push(a0.concat(a1))));
        return tmp;
      }, [[]]);
    }
    .as-console-wrapper { top: 0; max-height: 100% !important; }

    0 讨论(0)
  • 2020-12-21 00:59

    Exhaustive testing, as the accepted answer offers, is probably the most reasonable practical tack here. Moreover, new currencies do not arise, and old currencies do not die, with particular frequency. The currencies supported by any implementation being kept up to date, are going to reflect reality almost always. So the try-and-see approach really isn't going to fail much.

    But to elaborate further on this from the spec side, the spec really only cares about currencies being "well-formed": three ASCII letters. If the resulting code is a known currency, you will get congenial behavior. Otherwise, you get roughly graceful fallback to the code itself. So there's debatably not a need to expose the supported list: currency codes are at least a relatively understandable thing to many users, probably, as in most UI seeing something like "3 USD" or "5 CAD" where prices or costs are implicated is going to connote the user's currency generally.

    0 讨论(0)
提交回复
热议问题