UNPKG

n2words

Version:

Convert numbers to words in 70+ languages with zero dependencies. Supports BigInt, decimals, and browser/Node.js environments.

90 lines (75 loc) 2.69 kB
/** * Currency value parsing utility. * Optimized parser for currency conversion - extracts dollars and cents. * @module parse-currency */ import { expandScientificNotation, hasScientificNotation, numberToString } from './expand-scientific.js' /** * Parses a value for currency conversion. * Returns dollars and cents as separate bigints, plus negative flag. * @param {number|string|bigint} value - The value to parse * @returns {{isNegative: boolean, dollars: bigint, cents: bigint}} The parsed dollars and cents with a negative flag. * @throws {TypeError} If value is not number, string, or bigint * @throws {RangeError} If value is not finite */ export function parseCurrencyValue(value) { const type = typeof value // BigInt: whole dollars only if (typeof value === 'bigint') { return value < 0n ? { isNegative: true, dollars: -value, cents: 0n } : { isNegative: false, dollars: value, cents: 0n } } // Number: fast path for safe integers if (typeof value === 'number') { if (!Number.isFinite(value)) { throw new RangeError('Currency must be a finite number') } if (Number.isSafeInteger(value)) { return value < 0 ? { isNegative: true, dollars: BigInt(-value), cents: 0n } : { isNegative: false, dollars: BigInt(value), cents: 0n } } // Non-integer or unsafe: convert to string return parseCurrencyString(numberToString(value)) } // String input if (typeof value === 'string') { return parseCurrencyString(value) } throw new TypeError( `Invalid value type: expected number, string, or bigint, received ${type}`, ) } /** * Parses a string for currency conversion. * @param {string} value - The string to parse * @returns {{isNegative: boolean, dollars: bigint, cents: bigint}} The parsed dollars and cents with a negative flag. */ function parseCurrencyString(value) { let str = value.trim() if (str.length === 0 || Number.isNaN(Number(str))) { throw new RangeError(`Invalid currency format: "${value}"`) } // Expand scientific notation if (hasScientificNotation(str)) { str = expandScientificNotation(str) } // Handle negative const isNegative = str[0] === '-' if (isNegative) str = str.slice(1) // Split on decimal const dotIndex = str.indexOf('.') if (dotIndex === -1) { return { isNegative, dollars: BigInt(str), cents: 0n } } const dollarStr = str.slice(0, dotIndex) || '0' const decimalPart = str.slice(dotIndex + 1) // Truncate to 2 decimal places and pad if needed const centStr = (decimalPart + '00').slice(0, 2) return { isNegative, dollars: BigInt(dollarStr), cents: BigInt(centStr), } }