tanisa
Version:
A utility to convert Malagasy 🇲🇬 numbers, dates, and times into their word representations.
140 lines (139 loc) • 6.64 kB
JavaScript
;
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;