diff --git a/doc/api/currency/currency-formatter.md b/doc/api/currency/currency-formatter.md index c649f0973..c65093c71 100644 --- a/doc/api/currency/currency-formatter.md +++ b/doc/api/currency/currency-formatter.md @@ -20,6 +20,8 @@ Number to be formatted, eg. `9.99`. ### Example +#### Static Formatter + Prior to using any currency methods, you must load `cldr/main/{locale}/currencies.json`, `cldr/supplemental/currencyData.json`, and the CLDR content required by the number module. If using plural messages, you also must load the CLDR content required by the plural module. Read [CLDR content][] if you need more information. [CLDR content]: ../../../README.md#2-cldr-content @@ -37,6 +39,8 @@ formatter( 9.99 ); ``` +#### Instance Formatter + You can use the instance method `.currencyFormatter()`, which uses the instance locale. ```javascript @@ -62,6 +66,8 @@ For comparison, follow the formatting output of different symbols in different l | `.currencyFormatter( "GBP" )( 1 )` | `£1.00` | `1,00 £` | `£ 1.00` | | `.currencyFormatter( "BRL" )( 1 )` | `R$1.00` | `1,00 R$` | `R$ 1.00` | +#### Configuring style + For the accounting variation of the symbol format, use `style: "accounting"`. ```javascript @@ -109,6 +115,8 @@ formatter( 9.99 ); // > "9.99 USD" ``` +#### Configuring inherited number options + Override the number of digits, grouping separators, rounding function or any other [`.numberFormatter()` options](../number/number-formatter.md). ```javascript @@ -129,16 +137,39 @@ formatter = Globalize.currencyFormatter( "USD", { formatter( 1.491 ); // > "$1.50" +``` -formatter = Globalize.currencyFormatter( "USD", { - maximumFractionDigits: 0, +#### Formatting Compact Currencies + +```js +var shortFormatter = Globalize( "en" ).currencyFormatter( "USD", { compact: "short" }); -formatter( 12830000000 ); +var longFormatter = Globalize( "en" ).currencyFormatter( "USD", { + compact: "long" +}); + +shortFormatter( 12830000000 ); // > "$13B" + +longFormatter( 12830000000 ); +// > "$13 billion" ``` +The minimumSignificantDigits and maximumSignificantDigits options are specially useful to control the number of digits to display. + +```js +Globalize( "en" ).formatCurrency( 12830000000, "USD", { + compact: "short", + minimumSignificantDigits: 3, + maximumSignificantDigits: 3 +}); +// > "$12.8B" +``` + +#### Performance Suggestion + For improved performance on iterations, first create the formatter. Then, reuse it on each loop. ```javascript diff --git a/doc/api/number/number-formatter.md b/doc/api/number/number-formatter.md index d8e01d807..dc51802d2 100644 --- a/doc/api/number/number-formatter.md +++ b/doc/api/number/number-formatter.md @@ -149,15 +149,11 @@ Long numbers can be represented in a compact format, with `short` using abbrevia ```javascript var shortFormatter = Globalize( "en" ).numberFormatter({ - compact: "short", - maximumFractionDigits: 0, - style: "decimal" + compact: "short" }); var longFormatter = Globalize( "en" ).numberFormatter({ - compact: "long", - maximumFractionDigits: 0, - style: "decimal" + compact: "long" }); shortFormatter( 27588910 ); @@ -167,6 +163,17 @@ longFormatter( 27588910 ); // > "28 million" ``` +The minimumSignificantDigits and maximumSignificantDigits options are specially useful to control the number of digits to display. + +```js +Globalize( "en" ).formatNumber( 27588910, { + compact: "short", + minimumSignificantDigits: 3, + maximumSignificantDigits: 3 +}); +// > "27.6M" +``` + #### Configuring Rounding Numbers with a decreased amount of decimal places can be rounded up, rounded down, rounded arithmetically, or truncated by setting the `round` option to `ceil`, `floor`, `round` (default), or `truncate`. diff --git a/src/number/compact-pattern-re.js b/src/number/compact-pattern-re.js new file mode 100644 index 000000000..dc4840ad7 --- /dev/null +++ b/src/number/compact-pattern-re.js @@ -0,0 +1,21 @@ +define(function() { + +/** + * EBNF representation: + * + * compact_pattern_re = prefix? + * number_pattern_re + * suffix? + * + * number_pattern_re = 0+ + * + * Regexp groups: + * + * 0: compact_pattern_re + * 1: prefix + * 2: number_pattern_re (the number pattern to use in compact mode) + * 3: suffix + */ +return ( /^([^0]*)(0+)([^0]*)$/ ); + +}); diff --git a/src/number/compact.js b/src/number/compact.js index 52ae93a84..24771ca79 100644 --- a/src/number/compact.js +++ b/src/number/compact.js @@ -1,5 +1,5 @@ define([ - "./numbering-system" + "./numbering-system" ], function( numberNumberingSystem ) { /** @@ -12,11 +12,26 @@ define([ * Return the localized compact map for the given compact mode. */ return function( compactType, cldr ) { - return cldr.main([ - "numbers/decimalFormats-numberSystem-" + numberNumberingSystem( cldr ), - compactType, - "decimalFormat" - ]); + var maxExponent = 0; + + var object = cldr.main([ + "numbers/decimalFormats-numberSystem-" + numberNumberingSystem( cldr ), + compactType, + "decimalFormat" + ]); + + object = Object.keys( object ).reduce(function( newObject, compactKey ) { + var numberExponent = compactKey.split( "0" ).length - 1; + var pluralForm = compactKey.split( "-" )[ 2 ]; + newObject[ numberExponent ] = newObject[ numberExponent ] || {}; + newObject[ numberExponent ][ pluralForm ] = object[ compactKey ]; + maxExponent = Math.max( numberExponent, maxExponent ); + return newObject; + }, {}); + + object.maxExponent = maxExponent; + + return object; }; }); diff --git a/src/number/format-properties.js b/src/number/format-properties.js index 79a602499..0eee708db 100644 --- a/src/number/format-properties.js +++ b/src/number/format-properties.js @@ -65,6 +65,18 @@ return function( pattern, cldr, options ) { ]); if ( options.compact ) { + + // The compact digits number pattern is always `0+`, so override the following properties. + // Note: minimumIntegerDigits would actually range from `0` to `000` based on the scale of + // the value to be formatted, though we're always using 1 as a simplification, because the + // number won't be zero-padded since we chose the right format based on the scale, i.e., + // we'd never see something like `003M` anyway. + properties[ 2 ] = negativeSuffix[ 2 ] = 1; // minimumIntegerDigits + properties[ 3 ] = negativeSuffix[ 3 ] = 0; // minimumFractionDigits + properties[ 4 ] = negativeSuffix[ 4 ] = 0; // maximumFractionDigits + properties[ 5 ] = negativeSuffix[ 5 ] = // minimumSignificantDigits & + properties[ 6 ] = negativeSuffix[ 6 ] = undefined ; // maximumSignificantDigits + properties[20] = numberCompact( options.compact, cldr ); } diff --git a/src/number/format.js b/src/number/format.js index 2fc06bc6f..448ee0079 100644 --- a/src/number/format.js +++ b/src/number/format.js @@ -1,11 +1,13 @@ define([ + "./compact-pattern-re", "./format/grouping-separator", "./format/integer-fraction-digits", "./format/significant-digits", "./pattern-re", "../util/remove-literal-quotes" -], function( numberFormatGroupingSeparator, numberFormatIntegerFractionDigits, - numberFormatSignificantDigits, numberPatternRe, removeLiteralQuotes ) { +], function( numberCompactPatternRe, numberFormatGroupingSeparator, + numberFormatIntegerFractionDigits, numberFormatSignificantDigits, numberPatternRe, + removeLiteralQuotes ) { /** * format( number, properties ) @@ -68,29 +70,24 @@ return function( number, properties, pluralGenerator ) { number *= 1000; } - var compactPattern, compactDigits, compactProperties, divisor, pluralForm, zeroes, - originalNumber; + var compactPattern, compactDigits, compactProperties, divisor, numberExponent, pluralForm; // Compact mode: initial number digit processing if ( compactMap ) { - originalNumber = number; - zeroes = Array( Math.floor( number ).toString().length ).join( "0" ); - if ( zeroes.length >= 3 ) { - - // use default plural form to perform initial decimal shift - compactPattern = compactMap[ "1" + zeroes + "-count-other" ]; - - if ( compactPattern ) { - compactDigits = compactPattern.split( "0" ).length - 1; - divisor = zeroes.length - ( compactDigits - 1 ); - number = number / Math.pow( 10, divisor ); - - // Some languages specify no pattern for certain digit lengths, represented as "0". - // If no pattern, original number should remain uncompacted. - if ( compactPattern === "0" ) { - number = originalNumber; - } - } + numberExponent = Math.floor( number ).toString().length - 1; + numberExponent = Math.min( numberExponent, compactMap.maxExponent ); + + // Use default plural form to perform initial decimal shift + if ( numberExponent >= 3 ) { + compactPattern = compactMap[ numberExponent ] && compactMap[ numberExponent ].other; + } + + if ( compactPattern === "0" ) { + compactPattern = null; + } else if ( compactPattern ) { + compactDigits = compactPattern.split( "0" ).length - 1; + divisor = numberExponent - ( compactDigits - 1 ); + number = number / Math.pow( 10, divisor ); } } @@ -107,18 +104,16 @@ return function( number, properties, pluralGenerator ) { // Compact mode: apply formatting if ( compactMap && compactPattern ) { - pluralForm = pluralGenerator ? pluralGenerator( number ) : "other"; - compactPattern = compactMap[ "1" + zeroes + "-count-" + pluralForm ] || compactPattern; - // Some languages specify no pattern for certain digit lengths, represented as "0". - // Only apply compact pattern if one is specified. - if ( compactPattern !== "0" ) { - compactProperties = compactPattern.match( numberPatternRe ); + // Get plural form after possible roundings + pluralForm = pluralGenerator ? pluralGenerator( +number ) : "other"; - // update prefix/suffix with compact prefix/suffix - prefix += compactProperties[ 1 ]; - suffix = compactProperties[ 11 ] + suffix; - } + compactPattern = compactMap[ numberExponent ][ pluralForm ] || compactPattern; + compactProperties = compactPattern.match( numberCompactPatternRe ); + + // update prefix/suffix with compact prefix/suffix + prefix += compactProperties[ 1 ]; + suffix = compactProperties[ 3 ] + suffix; } // Remove the possible number minus sign diff --git a/src/number/pattern-re.js b/src/number/pattern-re.js index bbb0b0893..2d2b206b1 100644 --- a/src/number/pattern-re.js +++ b/src/number/pattern-re.js @@ -26,7 +26,7 @@ define(function() { * * suffix = non_number_stuff * - * non_number_stuff = regexp(.*?) + * non_number_stuff = regexp(('[^']+'|''|[^*#@0,.E])*) * * * Regexp groups: @@ -45,6 +45,6 @@ define(function() { * 11: suffix * 12: - */ -return ( /^(('([^']|'')*'|[^*#@0,.E])*)(\*.)?((([#,]*[0,]*0+)(\.0*[0-9]*#*)?)|([#,]*@+#*))(E\+?0+)?(.*?)$/ ); +return ( /^(('([^']|'')*'|[^*#@0,.E])*)(\*.)?((([#,]*[0,]*0+)(\.0*[0-9]*#*)?)|([#,]*@+#*))(E\+?0+)?(('[^']+'|''|[^*#@0,.E])*)$/ ); }); diff --git a/test/unit/number/format.js b/test/unit/number/format.js index b47d7217b..d880b4d09 100644 --- a/test/unit/number/format.js +++ b/test/unit/number/format.js @@ -44,12 +44,8 @@ zhSimplified = new Cldr( "zh" ); QUnit.module( "Number Format" ); -function oneOrOtherPluralGenerator( plural ) { - if ( plural === "1" ) { - return "one"; - } else { - return "other"; - } +function esPluralGenerator( n ) { + return ( n === 1 ) ? "one" : "other"; } /** @@ -81,123 +77,6 @@ QUnit.test( "should format negative integer", function( assert ) { assert.equal( format( -earthDiameter, properties( "0;(0.0##)", en ) ), "(12735)" ); }); -/** - * Compact Numbers - */ - -QUnit.test( "integers should format in compact mode", function( assert ) { - assert.equal( format( 273.7, properties( "#0", en, { compact: "short" } ) ), "274" ); - assert.equal( format( 273.7, properties( "#0", en, { compact: "long" } ) ), "274" ); - assert.equal( format( 273, properties( "#0", en, { compact: "short" } ) ), "273" ); - assert.equal( format( 273, properties( "#0", en, { compact: "long" } ) ), "273" ); - assert.equal( format( 573, properties( "#0", en, { compact: "short" } ) ), "573" ); - assert.equal( format( 573, properties( "#0", en, { compact: "long" } ) ), "573" ); - assert.equal( format( 1273, properties( "#0", en, { compact: "short" } ) ), "1K" ); - assert.equal( format( 1273, properties( "#0", en, { compact: "long" } ) ), "1 thousand" ); - assert.equal( format( 1273000, properties( "#0", es, { - compact: "long" - } ), oneOrOtherPluralGenerator ), "1 millón" ); - assert.equal( format( 2273000, properties( "#0", es, { - compact: "long" - } ), oneOrOtherPluralGenerator ), "2 millones" ); - assert.equal( format( 9999.9, properties( "#0", en, { compact: "long" } ) ), "10 thousand" ); - assert.equal( format( 12735, properties( "#0", en, { compact: "short" } ) ), "13K" ); - assert.equal( format( 12735, properties( "#0", en, { compact: "long" } ) ), "13 thousand" ); - assert.equal( format( 127350, properties( "#0", en, { compact: "short" } ) ), "127K" ); - assert.equal( format( 127350, properties( "#0", en, { compact: "long" } ) ), "127 thousand" ); - assert.equal( format( 1273500, properties( "#0", en, { compact: "short" } ) ), "1M" ); - assert.equal( format( 1273500, properties( "#0", en, { compact: "long" } ) ), "1 million" ); - assert.equal( format( -1273500, properties( "#0", en, { compact: "short" } ) ), "-1M" ); - assert.equal( format( -1273500, properties( "#0", en, { compact: "long" } ) ), "-1 million" ); - assert.equal( format( -1273500, properties( "#0;(#0)", en, { compact: "short" } ) ), "(1M)" ); - assert.equal( format( -1273500, properties( "#0;(#0)", en, { compact: "long" } ) ), "(1 million)" ); - - // some hungarian short formats have a terminating E, which is treated as a special - // character in non-compact formats - // \u00A0 is a unicode non-breaking space - assert.equal( format( 1273, properties( "#0", hu, { compact: "short" } ) ), "1\u00A0E" ); - assert.equal( format( 1273, properties( "#0", hu, { compact: "long" } ) ), "1 ezer" ); - assert.equal( format(9000000, properties( "#0", hu, { compact: "short" } ) ), "9\u00A0M" ); - assert.equal( format(9000000, properties( "#0", hu, { compact: "long" } ) ), "9 millió" ); -}); - -QUnit.test( "unsupported numbers should apply no compacting in compact mode", function( assert ) { - assert.equal( format( 0.01, properties( "#0.##", en, { compact: "short" } ) ), "0.01" ) - assert.equal( format( 1234000000000000, properties( "#0", en, { compact: "short" } ) ), "1234000000000000" ) -}); - -QUnit.test( "decimals should format in compact mode", function( assert ) { - assert.equal( format( 273.7, properties( "#0.#", en, { compact: "short" } ) ), "273.7" ); - assert.equal( format( 273.7, properties( "#0.#", en, { compact: "long" } ) ), "273.7" ); - assert.equal( format( 273, properties( "#0.#", en, { compact: "short" } ) ), "273" ); - assert.equal( format( 273, properties( "#0.#", en, { compact: "long" } ) ), "273" ); - assert.equal( format( 573, properties( "#0.#", en, { compact: "short" } ) ), "573" ); - assert.equal( format( 573, properties( "#0.#", en, { compact: "long" } ) ), "573" ); - assert.equal( format( 1273, properties( "#0.#", en, { compact: "short" } ) ), "1.3K" ); - assert.equal( format( 1273, properties( "#0.#", en, { compact: "long" } ) ), "1.3 thousand" ); - assert.equal( format( 1273000, properties( "#0.#", es, { - compact: "long" - } ), oneOrOtherPluralGenerator ), "1,3 millones" ); - assert.equal( format( 2273000, properties( "#0.#", es, { - compact: "long" - } ), oneOrOtherPluralGenerator ), "2,3 millones" ); - assert.equal( format( 9999.9, properties( "#0.#", en, { compact: "long" } ) ), "10 thousand" ); - assert.equal( format( 12735, properties( "#0.#", en, { compact: "short" } ) ), "12.7K" ); - assert.equal( format( 12735, properties( "#0.#", en, { compact: "long" } ) ), "12.7 thousand" ); - assert.equal( format( 127350, properties( "#0.#", en, { compact: "short" } ) ), "127.4K" ); - assert.equal( format( 127350, properties( "#0.#", en, { compact: "long" } ) ), "127.4 thousand" ); - assert.equal( format( 1273500, properties( "#0.#", en, { compact: "short" } ) ), "1.3M" ); - assert.equal( format( 1273500, properties( "#0.#", en, { compact: "long" } ) ), "1.3 million" ); - assert.equal( format( -1273500, properties( "#0.#", en, { compact: "short" } ) ), "-1.3M" ); - assert.equal( format( -1273500, properties( "#0.#", en, { compact: "long" } ) ), "-1.3 million" ); - assert.equal( format( -1273500, properties( "#0.#;(#0.#)", en, { compact: "short" } ) ), "(1.3M)" ); - assert.equal( format( -1273500, properties( "#0.#;(#0.#)", en, { compact: "long" } ) ), "(1.3 million)" ); -}); - -QUnit.test( "decimals should support rounding in compact mode", function( assert ) { - assert.equal( format( 12735, properties( "#0.##", en, { - compact: "short", - maximumFractionDigits: 2, - minimumFractionDigits: 1 - } ) ), "12.74K" ); - assert.equal( format( 12735, properties( "#0.##", en, { - compact: "short", - maximumFractionDigits: 2, - minimumFractionDigits: 1, - round: "ceil" - } ) ), "12.74K" ); - assert.equal( format( 12735, properties( "#0.##", en, { - compact: "short", - maximumFractionDigits: 2, - minimumFractionDigits: 1, - round: "floor" - } ) ), "12.73K" ); - assert.equal( format( 12735, properties( "#0.##", en, { - compact: "short", - maximumFractionDigits: 2, - minimumFractionDigits: 1, - round: "truncate" - } ) ), "12.73K" ); -}); - -QUnit.test( "integers should support significant digits in compact mode", function( assert ) { - assert.equal( format( 12735, properties( "@@@", en, { compact: "short" } ) ), "12.7K" ); - assert.equal( format( 12735, properties( "@@", en, { compact: "short" } ) ), "13K" ); - assert.equal( format( 12735, properties( "@", en, { compact: "short" } ) ), "10K" ); -}); - -QUnit.test( "integers should handle default (no) pattern in compact mode", function( assert ) { - assert.equal( format( 2737, properties( "#0.#", zhSimplified, { compact: "short" } ) ), "2737" ); - assert.equal( format( 2737, properties( "#0.#", zhSimplified, { compact: "long" } ) ), "2737" ); - assert.equal( format( 27371, properties( "#0.#", zhSimplified, { compact: "short" } ) ), "2.7万" ); - assert.equal( format( 27371, properties( "#0.#", zhSimplified, { compact: "long" } ) ), "2.7万" ); -}); - -QUnit.test( "percents should format in compact mode", function( assert ) { - assert.equal( format( 127, properties( "#0%", en, { compact: "short" } ) ), "13K%" ); - assert.equal( format( 127, properties( "#0%", en, { compact: "long" } ) ), "13 thousand%" ); -}); - /** * Decimals */ @@ -427,9 +306,207 @@ QUnit.test( "should format infinite numbers", function( assert ) { QUnit.test( "should format literal (')", function( assert ) { assert.equal( format( 69900, properties( "'$'#,##0", en ) ), "$69,900" ); + assert.equal( format( 69900, properties( "'$'#,##0.00", en ) ), "$69,900.00" ); // Make sure quoted characters (in this case, minus sign) aren't localized. assert.equal( format( -pi, properties( "0.##;'-'0.##", fa ) ), "-۳٫۱۴" ); }); +/** + * Compact Numbers + */ + +QUnit.test( "should format numbers in compact mode", function( assert ) { + assert.equal( format( 273.7, properties( "0", en, { compact: "short" } ) ), "274" ); + assert.equal( format( 273.7, properties( "0", en, { compact: "long" } ) ), "274" ); + assert.equal( format( 273, properties( "0", en, { compact: "short" } ) ), "273" ); + assert.equal( format( 273, properties( "0", en, { compact: "long" } ) ), "273" ); + assert.equal( format( 573, properties( "0", en, { compact: "short" } ) ), "573" ); + assert.equal( format( 573, properties( "0", en, { compact: "long" } ) ), "573" ); + assert.equal( format( 1273, properties( "0", en, { compact: "short" } ) ), "1K" ); + assert.equal( format( 1273, properties( "0", en, { compact: "long" } ) ), "1 thousand" ); + assert.equal( format( 1234000000000000, properties( "0", en, { compact: "short" } ) ), "1234T" ); + assert.equal( format( 1273000, properties( "0", es, { + compact: "long" + } ), esPluralGenerator ), "1 millón" ); + assert.equal( format( 2273000, properties( "0", es, { + compact: "long" + } ), esPluralGenerator ), "2 millones" ); + assert.equal( format( 27371, properties( "0", zhSimplified, { compact: "short" } ) ), "3万" ); + assert.equal( format( 27371, properties( "0", zhSimplified, { compact: "long" } ) ), "3万" ); + assert.equal( format( 9999.9, properties( "0", en, { compact: "long" } ) ), "10 thousand" ); + assert.equal( format( 12735, properties( "0", en, { compact: "short" } ) ), "13K" ); + assert.equal( format( 12735, properties( "0", en, { compact: "long" } ) ), "13 thousand" ); + assert.equal( format( 127350, properties( "0", en, { compact: "short" } ) ), "127K" ); + assert.equal( format( 127350, properties( "0", en, { compact: "long" } ) ), "127 thousand" ); + assert.equal( format( 1273500, properties( "0", en, { compact: "short" } ) ), "1M" ); + assert.equal( format( 1273500, properties( "0", en, { compact: "long" } ) ), "1 million" ); + assert.equal( format( -1273500, properties( "0", en, { compact: "short" } ) ), "-1M" ); + assert.equal( format( -1273500, properties( "0", en, { compact: "long" } ) ), "-1 million" ); + assert.equal( format( -1273500, properties( "0;(0)", en, { compact: "short" } ) ), "(1M)" ); + assert.equal( format( -1273500, properties( "0;(0)", en, { compact: "long" } ) ), "(1 million)" ); + + // Some hungarian short formats have a terminating E, which is treated as a special + // character in non-compact formats. + // \u00A0 is a unicode non-breaking space. + assert.equal( format( 1273, properties( "0", hu, { compact: "short" } ) ), "1\u00A0E" ); + assert.equal( format( 1273, properties( "0", hu, { compact: "long" } ) ), "1 ezer" ); + assert.equal( format( 9000000, properties( "0", hu, { compact: "short" } ) ), "9\u00A0M" ); + assert.equal( format( 9000000, properties( "0", hu, { compact: "long" } ) ), "9 millió" ); +}); + +QUnit.test( "should format numbers that lack pattern in compact mode (use default compact mode pattern)", function( assert ) { + assert.equal( format( 0.01, properties( "0", en, { compact: "short" } ) ), "0" ); + assert.equal( format( 273.7, properties( "0", en, { compact: "short" } ) ), "274" ); + assert.equal( format( 273.7, properties( "0", en, { compact: "long" } ) ), "274" ); + assert.equal( format( 2737, properties( "0", zhSimplified, { compact: "short" } ) ), "2737" ); + assert.equal( format( 2737, properties( "0", zhSimplified, { compact: "long" } ) ), "2737" ); +}); + +QUnit.test( "numbers should support fraction digits in compact mode", function( assert ) { + assert.equal( format( 1273, properties( "0", en, { + compact: "short", + maximumFractionDigits: 1, + minimumFractionDigits: 1 + })), "1.3K" ); + assert.equal( format( 1273, properties( "0", en, { + compact: "long", + maximumFractionDigits: 1, + minimumFractionDigits: 1 + })), "1.3 thousand" ); + assert.equal( format( 1273000, properties( "0", es, { + compact: "long", + maximumFractionDigits: 1, + minimumFractionDigits: 1 + }), esPluralGenerator ), "1,3 millones" ); + assert.equal( format( 2273000, properties( "0", es, { + compact: "long", + maximumFractionDigits: 1, + minimumFractionDigits: 1 + } ), esPluralGenerator ), "2,3 millones" ); + assert.equal( format( 12735, properties( "0", en, { + compact: "short", + maximumFractionDigits: 1, + minimumFractionDigits: 1 + })), "12.7K" ); + assert.equal( format( 12735, properties( "0", en, { + compact: "long", + maximumFractionDigits: 1, + minimumFractionDigits: 1 + })), "12.7 thousand" ); + assert.equal( format( 127350, properties( "0", en, { + compact: "short", + maximumFractionDigits: 1, + minimumFractionDigits: 1 + })), "127.4K" ); + assert.equal( format( 127350, properties( "0", en, { + compact: "long", + maximumFractionDigits: 1, + minimumFractionDigits: 1 + })), "127.4 thousand" ); + assert.equal( format( 1273500, properties( "0", en, { + compact: "short", + maximumFractionDigits: 1, + minimumFractionDigits: 1 + })), "1.3M" ); + assert.equal( format( 1273500, properties( "0", en, { + compact: "long", + maximumFractionDigits: 1, + minimumFractionDigits: 1 + })), "1.3 million" ); + assert.equal( format( -1273500, properties( "0", en, { + compact: "short", + maximumFractionDigits: 1, + minimumFractionDigits: 1 + })), "-1.3M" ); + assert.equal( format( -1273500, properties( "0", en, { + compact: "long", + maximumFractionDigits: 1, + minimumFractionDigits: 1 + })), "-1.3 million" ); + assert.equal( format( -1273500, properties( "0;(0)", en, { + compact: "short", + maximumFractionDigits: 1, + minimumFractionDigits: 1 + })), "(1.3M)" ); + assert.equal( format( -1273500, properties( "0;(0)", en, { + compact: "long", + maximumFractionDigits: 1, + minimumFractionDigits: 1 + })), "(1.3 million)" ); +}); + +QUnit.test( "numbers should support significant digits in compact mode", function( assert ) { + assert.equal( format( 12735, properties( "0", en, { + compact: "short", + maximumSignificantDigits: 3, + minimumSignificantDigits: 3 + })), "12.7K" ); + assert.equal( format( 12735, properties( "0", en, { + compact: "short", + maximumSignificantDigits: 2, + minimumSignificantDigits: 2 + })), "13K" ); + assert.equal( format( 12735, properties( "0", en, { + compact: "short", + maximumSignificantDigits: 1, + minimumSignificantDigits: 1 + })), "10K" ); +}); + +QUnit.test( "numbers should support rounding in compact mode", function( assert ) { + assert.equal( format( 12735, properties( "0", en, { + compact: "short", + maximumFractionDigits: 2, + minimumFractionDigits: 1 + } ) ), "12.74K" ); + assert.equal( format( 12735, properties( "0", en, { + compact: "short", + maximumFractionDigits: 2, + minimumFractionDigits: 1, + round: "ceil" + } ) ), "12.74K" ); + assert.equal( format( 12735, properties( "0", en, { + compact: "short", + maximumFractionDigits: 2, + minimumFractionDigits: 1, + round: "floor" + } ) ), "12.73K" ); + assert.equal( format( 12735, properties( "0", en, { + compact: "short", + maximumFractionDigits: 2, + minimumFractionDigits: 1, + round: "truncate" + } ) ), "12.73K" ); +}); + +QUnit.test( "percents should format in compact mode", function( assert ) { + assert.equal( format( 127, properties( "0%", en, { compact: "short" } ) ), "13K%" ); + assert.equal( format( 127, properties( "0%", en, { compact: "long" } ) ), "13 thousand%" ); +}); + +QUnit.test( "given pattern properties should be ignored in compact mode", function( assert ) { + + // minimumIntegerDigits, minimumFractionDigits, maximumFractionDigits, minimumSignificantDigits, + // maximumSignificantDigits extracted from the pattern should be ignored. + assert.equal( format( 2737, properties( "0.#", en, { compact: "short" } ) ), "3K" ); + assert.equal( format( 2737, properties( "0.0", en, { compact: "short" } ) ), "3K" ); + assert.equal( format( 2737, properties( "0.0#", en, { compact: "short" } ) ), "3K" ); + assert.equal( format( 2737, properties( "@@", en, { compact: "short" } ) ), "3K" ); + assert.equal( format( 69900, properties( "'$'#,##0.00", en, {compact: "short"} ) ), "$70K" ); + + assert.equal( format( 12.01, properties( "0.#", en, { compact: "short" } ) ), "12" ); + assert.equal( format( 12.01, properties( "0.#", en, { compact: "short" } ) ), "12" ); + assert.equal( format( 12.01, properties( "0.0", en, { compact: "short" } ) ), "12" ); + assert.equal( format( 12.01, properties( "0.0#", en, { compact: "short" } ) ), "12" ); + assert.equal( format( 12.01, properties( "@@", en, { compact: "short" } ) ), "12" ); + assert.equal( format( 12.01, properties( "'$'#,##0.00", en, {compact: "short"} ) ), "$12" ); + + // Preserve grouping separator from original pattern. (only used in very big numbers) + assert.equal( format( 1234000000000000, properties( "#,##0", en, { compact: "short" } ) ), "1,234T" ); + + // Preserve prefix and suffix + assert.equal( format( 2737, properties( "(0.0#)", en, { compact: "short" } ) ), "(3K)" ); +}); + });