UNPKG

tanisa

Version:

A utility to convert Malagasy 🇲🇬 numbers, dates, and times into their word representations.

140 lines (139 loc) • 6.64 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.Tanisa = void 0; const dictionary_1 = require("./dictionary"); const date_1 = require("./date"); const time_1 = require("./time"); class Tanisa { toWords(number, options) { var _a, _b; const ignoreDecimal = (_a = options === null || options === void 0 ? void 0 : options.ignoreDecimal) !== null && _a !== void 0 ? _a : false; const decimalPlaces = (_b = options === null || options === void 0 ? void 0 : options.decimalPlaces) !== null && _b !== void 0 ? _b : -1; const numStr = String(number).trim(); if (typeof number === 'string' && /[eE]/.test(numStr)) { throw new TypeError(`Invalid number input: "${number}"`); } const [integerPartStr, decimalPartStr] = numStr.split('.'); const integerPartNum = parseInt(integerPartStr || '0', 10); if (isNaN(integerPartNum) || (decimalPartStr && decimalPartStr.length > 0 && isNaN(parseInt(decimalPartStr, 10)))) { throw new TypeError(`Invalid number input: "${number}"`); } if (numStr.startsWith('-') && (integerPartNum !== 0 || (decimalPartStr && parseInt(decimalPartStr, 10) > 0))) { throw new RangeError('Negative numbers are not supported.'); } if (integerPartNum >= dictionary_1.MalagasyNumerals.MAX_SUPPORTED_INTEGER || integerPartStr == dictionary_1.MalagasyNumerals.MAX_SUPPORTED_INTEGER.toString()) { throw new RangeError(`Number ${integerPartNum} exceeds the maximum supported value (${dictionary_1.MalagasyNumerals.MAX_SUPPORTED_INTEGER}).`); } const integerWords = this.convertInteger(integerPartNum); let decimalWords = ''; const processDecimals = decimalPartStr && decimalPartStr.length > 0 && !ignoreDecimal && decimalPlaces !== 0; if (processDecimals) { let effectiveDecimalPartStr = decimalPartStr; if (decimalPlaces > 0 && decimalPartStr.length > decimalPlaces) { effectiveDecimalPartStr = decimalPartStr.substring(0, decimalPlaces); } if (parseInt(effectiveDecimalPartStr || '0', 10) > 0) { let tempDecimalWords = ''; for (let i = 0; i < effectiveDecimalPartStr.length; i++) { const digit = effectiveDecimalPartStr[i]; if (digit === '0') { tempDecimalWords += dictionary_1.MalagasyNumerals.GLUE_DECIMAL_ZERO; } else { const remainingDecimal = effectiveDecimalPartStr.substring(i); tempDecimalWords += this.convertInteger(parseInt(remainingDecimal, 10)); break; } } if (tempDecimalWords) { decimalWords = dictionary_1.MalagasyNumerals.GLUE_FAINGO + tempDecimalWords; } } } return integerWords + decimalWords; } toDate(input, options) { const { year, month, day } = (0, date_1.parseDate)(input); if ((options === null || options === void 0 ? void 0 : options.format) === 'long') { return (0, date_1.formatLongDate)(year, month, day, (n) => this.toWords(n)); } return (0, date_1.formatShortDate)(year, month, day); } toTime(input, options) { var _a; const { hours, minutes, seconds } = (0, time_1.parseTime)(input); return (0, time_1.formatTime)(hours, minutes, seconds, (_a = options === null || options === void 0 ? void 0 : options.precision) !== null && _a !== void 0 ? _a : 'minutes', (n) => this.toWords(n)); } convertInteger(num) { if (num === 0) return dictionary_1.MalagasyNumerals.ZERO; for (const unit of dictionary_1.MalagasyNumerals.LARGE_NUMBER_UNITS) { if (num >= unit.threshold) return this.formatLargeNumber(num, unit); } return this.convertBelowThousand(num); } formatLargeNumber(num, unit) { const multiple = Math.floor(num / unit.threshold); const remainder = num % unit.threshold; let prefix = ''; if (multiple > 1) { prefix = this.convertInteger(multiple) + ' '; } else if (multiple === 1 && unit.threshold > 1000) { prefix = dictionary_1.MalagasyNumerals.DIGITS[1] + ' '; } const basePart = prefix + unit.name; if (remainder > 0) { return (this.convertInteger(remainder) + dictionary_1.MalagasyNumerals.GLUE_SY + basePart); } return basePart; } convertBelowThousand(num) { if (num >= 100) { const hundredMultiple = Math.floor(num / 100); const remainder = num % 100; const hundredWord = dictionary_1.MalagasyNumerals.HUNDREDS[hundredMultiple]; if (remainder === 0) return hundredWord; const remainderWords = this.convertBelowHundred(remainder); const glue = hundredMultiple >= 2 && remainder >= 10 ? dictionary_1.MalagasyNumerals.GLUE_SY : dictionary_1.MalagasyNumerals.GLUE_AMBY; const finalRemainder = remainder === 1 ? dictionary_1.MalagasyNumerals.CUSTOM_ONE : remainderWords; return finalRemainder + glue + hundredWord; } return this.convertBelowHundred(num); } convertTeens(num) { const ones = num - 10; const digitWord = ones === 1 ? dictionary_1.MalagasyNumerals.CUSTOM_ONE : dictionary_1.MalagasyNumerals.DIGITS[ones]; return digitWord + dictionary_1.MalagasyNumerals.GLUE_AMBIN_NY + dictionary_1.MalagasyNumerals.TENS[1]; } convertBelowHundred(num) { if (num >= 10) { if (num > 10 && num < 20) return this.convertTeens(num); const tenMultiple = Math.floor(num / 10); const remainder = num % 10; const tenWord = dictionary_1.MalagasyNumerals.TENS[tenMultiple]; if (remainder === 0) return tenWord; const digitWord = remainder === 1 ? dictionary_1.MalagasyNumerals.CUSTOM_ONE : dictionary_1.MalagasyNumerals.DIGITS[remainder]; return digitWord + dictionary_1.MalagasyNumerals.GLUE_AMBY + tenWord; } return dictionary_1.MalagasyNumerals.DIGITS[num]; } } exports.Tanisa = Tanisa;