UNPKG

@telerik/kendo-intl

Version:

A package exporting functions for date and number parsing and formatting

137 lines (107 loc) 4.4 kB
import { PERCENT, SCIENTIFIC, NUMBER_PLACEHOLDER, CURRENCY_PLACEHOLDER, PERCENT_PLACEHOLDER, EMPTY, POINT } from '../common/constants'; import isNegativeZero from '../common/is-negative-zero'; import formatCurrencySymbol from './format-currency-symbol'; import groupInteger from './group-integer'; import isCurrencyStyle from './is-currency-style'; import pad from '../common/pad'; import round from '../common/round'; import { currencyFractionOptions } from '../cldr'; const DEFAULT_DECIMAL_ROUNDING = 3; const DEFAULT_PERCENT_ROUNDING = 0; const trailingZeroRegex = /0+$/; function fractionOptions(options) { let { minimumFractionDigits, maximumFractionDigits, style } = options; const isCurrency = isCurrencyStyle(style); let currencyFractions; if (isCurrency) { currencyFractions = currencyFractionOptions(options.currency); } if (minimumFractionDigits === undefined) { minimumFractionDigits = isCurrency ? currencyFractions.minimumFractionDigits : 0; } if (maximumFractionDigits === undefined) { if (style === PERCENT) { maximumFractionDigits = Math.max(minimumFractionDigits, DEFAULT_PERCENT_ROUNDING); } else if (isCurrency) { maximumFractionDigits = Math.max(minimumFractionDigits, currencyFractions.maximumFractionDigits); } else { maximumFractionDigits = Math.max(minimumFractionDigits, DEFAULT_DECIMAL_ROUNDING); } } return { minimumFractionDigits: minimumFractionDigits, maximumFractionDigits: maximumFractionDigits }; } function applyPattern(value, pattern, symbol) { let result = EMPTY; for (let idx = 0, length = pattern.length; idx < length; idx++) { let ch = pattern.charAt(idx); if (ch === NUMBER_PLACEHOLDER) { result += value; } else if (ch === CURRENCY_PLACEHOLDER || ch === PERCENT_PLACEHOLDER) { result += symbol; } else { result += ch; } } return result; } function currencyUnitPattern(info, value) { const currencyInfo = info.numbers.currency; let pattern = value !== 1 ? currencyInfo["unitPattern-count-other"] : currencyInfo["unitPattern-count-one"]; if (value < 0) { pattern = pattern.replace(NUMBER_PLACEHOLDER, `-${ NUMBER_PLACEHOLDER }`); } return pattern; } export default function standardNumberFormat(number, options, info) { const symbols = info.numbers.symbols; const { style } = options; const isCurrency = isCurrencyStyle(style); //return number in exponential format if (style === SCIENTIFIC) { let exponential = options.minimumFractionDigits !== undefined ? number.toExponential(options.minimumFractionDigits) : number.toExponential(); return exponential.replace(POINT, symbols.decimal); } let value = number; let symbol; if (isCurrency) { options.value = value; symbol = formatCurrencySymbol(info, options); } if (style === PERCENT) { value *= 100; symbol = symbols.percentSign; } const { minimumFractionDigits, maximumFractionDigits } = fractionOptions(options); value = round(value, maximumFractionDigits); const negative = value < 0; const negativeZero = isNegativeZero(number); const parts = value.split(POINT); let integer = parts[0]; let fraction = pad(parts[1] ? parts[1].replace(trailingZeroRegex, EMPTY) : EMPTY, minimumFractionDigits, true); //exclude "-" if number is negative. if (negative) { integer = integer.substring(1); } if (options.minimumIntegerDigits) { integer = pad(integer, options.minimumIntegerDigits); } let formattedValue = options.useGrouping !== false ? groupInteger(integer, 0, integer.length, options, info) : integer; if (fraction) { formattedValue += symbols.decimal + fraction; } let pattern; if (isCurrency && options.currencyDisplay === "name") { pattern = currencyUnitPattern(info, number); } else { const patterns = options.patterns; pattern = (negative || negativeZero) ? patterns[1] || ("-" + patterns[0]) : patterns[0]; } if (pattern === NUMBER_PLACEHOLDER && !negative) { return formattedValue; } const result = applyPattern(formattedValue, pattern, symbol); return result; }