381 lines
8.7 KiB
TypeScript
381 lines
8.7 KiB
TypeScript
const oneDigit = [
|
||
"صفر",
|
||
"یک",
|
||
"دو",
|
||
"سه",
|
||
"چهار",
|
||
"پنج",
|
||
"شش",
|
||
"هفت",
|
||
"هشت",
|
||
"نه",
|
||
];
|
||
const twoDigits = {
|
||
10: "ده",
|
||
11: "یازده",
|
||
12: "دوازده",
|
||
13: "سیزده",
|
||
14: "چهارده",
|
||
15: "پانزده",
|
||
16: "شانزده",
|
||
17: "هفده",
|
||
18: "هجده",
|
||
19: "نوزده",
|
||
20: "بیست",
|
||
30: "سی",
|
||
40: "چهل",
|
||
50: "پنجاه",
|
||
60: "شصت",
|
||
70: "هفتاد",
|
||
80: "هشتاد",
|
||
90: "نود",
|
||
};
|
||
const threeDigits = {
|
||
100: "صد",
|
||
200: "دویست",
|
||
300: "سیصد",
|
||
400: "چهارصد",
|
||
500: "پانصد",
|
||
600: "شش صد",
|
||
700: "هفت صد",
|
||
800: "هشت صد",
|
||
900: "نه صد",
|
||
};
|
||
|
||
const types = ["تلیارد", "میلیارد", "میلیون", "هزار", ""];
|
||
const decimalTypes = ["دهم", "صدم", "هزارم", "ده هزارم"];
|
||
let numbers = [];
|
||
let decimals = [];
|
||
|
||
//Convert Number To Words
|
||
const convert = (number) => {
|
||
let negative = "";
|
||
let decNumber = "";
|
||
let decimal = "";
|
||
let percent = "";
|
||
|
||
if (isPercent(number)) {
|
||
number = number.replace("%", "");
|
||
percent = " درصد";
|
||
}
|
||
|
||
number = getString(number);
|
||
if (number == "") return "";
|
||
sliceNumber(number);
|
||
if (isNegative(number)) negative = "منفی ";
|
||
number = number.replace("-", "");
|
||
|
||
if (isDecimal(number)) {
|
||
let index = number.indexOf(".");
|
||
let decNumberStr = "";
|
||
|
||
decNumber = number.substr(index + 1, number.length);
|
||
number = number.substr(0, index);
|
||
decNumberStr = parseInt(decNumber).toString();
|
||
|
||
if (decNumberStr.length === 1 && decNumberStr != "0") {
|
||
decimal += oneDigit[decNumberStr] + " ";
|
||
decimal += decimalTypes[decNumber.length - 1];
|
||
} else {
|
||
decimal = calculateDigits(decimals);
|
||
decimal += " " + decimalTypes[decNumber.length - 1];
|
||
}
|
||
}
|
||
|
||
if (number.length === 1) {
|
||
if (!decimal) {
|
||
return negative + oneDigit[number] + percent;
|
||
}
|
||
|
||
if (number == "0") {
|
||
return negative + decimal + percent;
|
||
}
|
||
|
||
return negative + oneDigit[number] + " ممیز " + decimal + percent;
|
||
}
|
||
|
||
if (!decimal) {
|
||
return negative + calculateDigits(numbers) + percent;
|
||
}
|
||
|
||
return negative + calculateDigits(numbers) + " ممیز " + decimal + percent;
|
||
};
|
||
|
||
//split number 3 by 3 with a separator (123456789.3025=>123,456,789.3,025) Do Not Give It Persian Numbers
|
||
const sliceNumber = (number, separator = ",") => {
|
||
let percent = "";
|
||
let neg = "";
|
||
let dNum = "";
|
||
let n = "";
|
||
let d = "";
|
||
|
||
if (isPercent(number)) {
|
||
number = number.replace("%", "");
|
||
percent = "%";
|
||
}
|
||
|
||
number = getString(number);
|
||
|
||
if (number == "") return "";
|
||
if (isNegative(number)) neg = "-";
|
||
|
||
number = number.replace("-", "");
|
||
|
||
if (isDecimal(number)) {
|
||
let index = number.indexOf(".");
|
||
dNum = number.substr(index + 1, number.length);
|
||
number = number.substr(0, index);
|
||
}
|
||
|
||
n = putSeparator(number, separator);
|
||
numbers = n.split(separator);
|
||
|
||
if (!dNum) return neg + n + percent;
|
||
|
||
d = putSeparator(dNum, separator);
|
||
decimals = d.split(separator);
|
||
|
||
return neg + n + "." + d + percent;
|
||
};
|
||
|
||
//Puts a separator between the chunks of the given numString.
|
||
const putSeparator = (numString, separator = ",") => {
|
||
if (typeof numString !== "string") return "";
|
||
if (numString.length < 4) return numString;
|
||
|
||
let result = "";
|
||
for (let i = numString.length - 1, counter = 0; i >= 0; i--) {
|
||
if (counter == 3) {
|
||
result += separator;
|
||
counter = 0;
|
||
}
|
||
result += numString[i];
|
||
counter++;
|
||
}
|
||
|
||
result = result.split("").reverse().join("");
|
||
return result;
|
||
};
|
||
|
||
//Processing on Digits of A Number
|
||
const calculateDigits = (arrNum) => {
|
||
let result = "";
|
||
for (let i = 0; i < arrNum.length; i++) {
|
||
let parsedNum = parseInt(arrNum[i]);
|
||
let number = parsedNum;
|
||
let sadgan = Math.floor(number / 100) * 100;
|
||
number = number % 100;
|
||
let dahgan = Math.floor(number / 10) * 10;
|
||
let yekan = number % 10;
|
||
result += i !== 0 && parsedNum ? " و " : "";
|
||
|
||
result +=
|
||
getPersian(sadgan, dahgan, yekan, i, arrNum) + " " + getType(i, arrNum);
|
||
}
|
||
|
||
return result.trim();
|
||
};
|
||
|
||
//Main Process That Turn a Number Into a String(122=>100+20+2)
|
||
const getPersian = (sadgan, dahgan, yekan, index, numbers) => {
|
||
let flag = false;
|
||
let result = "";
|
||
let dahganPlusYekan = dahgan + yekan;
|
||
|
||
if (threeDigits[sadgan]) {
|
||
result +=
|
||
yekan > 0 || dahgan > 0
|
||
? threeDigits[sadgan] + " و "
|
||
: threeDigits[sadgan];
|
||
}
|
||
|
||
if (twoDigits[dahganPlusYekan]) {
|
||
result += twoDigits[dahganPlusYekan] + " ";
|
||
return result;
|
||
}
|
||
|
||
if (twoDigits[dahgan]) {
|
||
result += twoDigits[dahgan] + " و ";
|
||
}
|
||
|
||
if (
|
||
numbers.length === 2 &&
|
||
index === 0 &&
|
||
yekan === 1 &&
|
||
dahgan === 0 &&
|
||
sadgan === 0
|
||
) {
|
||
return result;
|
||
}
|
||
|
||
if (
|
||
numbers.length > 2 &&
|
||
index === numbers.length - 2 &&
|
||
yekan === 1 &&
|
||
dahgan === 0 &&
|
||
sadgan === 0
|
||
) {
|
||
return result;
|
||
}
|
||
|
||
if (yekan > 0) result += oneDigit[yekan] + " ";
|
||
|
||
return result;
|
||
};
|
||
|
||
//getting The Type Of Each Number (Billion, Million,...)
|
||
const getType = (i, numbers) => {
|
||
let parsedNum = parseInt(numbers[i]);
|
||
if (isNaN(parsedNum)) return "";
|
||
if (!parsedNum) return "";
|
||
let length = numbers.length - i;
|
||
let index = types.length - length;
|
||
return types[index];
|
||
};
|
||
|
||
//Calculate if number:String is Negative Or Not
|
||
const isNegative = (number) => {
|
||
number = getString(number);
|
||
if (!number) return false;
|
||
if (number[0] != "-") return false;
|
||
number = number.replace("-", "");
|
||
return number != "0";
|
||
};
|
||
|
||
//Calculate if number:String has '%' as Percent
|
||
const isPercent = (string) => {
|
||
if (typeof string !== "string") return false;
|
||
let index = string.indexOf("%");
|
||
let lIndex = string.lastIndexOf("%");
|
||
if (index != lIndex) return false;
|
||
return index > 0;
|
||
};
|
||
|
||
//is number:String:Number is a Valid Number? if type is Number turn it to String And Return it
|
||
const getString = (number) => {
|
||
if (number === undefined) return "";
|
||
if (number === null) return "";
|
||
if (isNaN(number)) return "";
|
||
if (typeof number === "number") return number.toString();
|
||
return number.trim();
|
||
};
|
||
|
||
//Calculate if number:String has Decimal Point Or Not
|
||
const isDecimal = (number) => {
|
||
number = getString(number);
|
||
if (number == "") return false;
|
||
let index = number.indexOf(".");
|
||
let lIndex = number.lastIndexOf(".");
|
||
if (index != lIndex) return false;
|
||
return index > 0;
|
||
};
|
||
//Convert English Numbers To Persian Numbers
|
||
const convertEnToPe = (number) => {
|
||
if (number == null || number == undefined) return "";
|
||
if (typeof number == "number") number = number.toString();
|
||
let res = "";
|
||
for (let i = 0; i < number.length; i++) {
|
||
switch (number[i]) {
|
||
case "\u0030":
|
||
res += "\u06F0";
|
||
break;
|
||
case "\u0031":
|
||
res += "\u06F1";
|
||
break;
|
||
case "\u0032":
|
||
res += "\u06F2";
|
||
break;
|
||
case "\u0033":
|
||
res += "\u06F3";
|
||
break;
|
||
case "\u0034":
|
||
res += "\u06F4";
|
||
break;
|
||
case "\u0035":
|
||
res += "\u06F5";
|
||
break;
|
||
case "\u0036":
|
||
res += "\u06F6";
|
||
break;
|
||
case "\u0037":
|
||
res += "\u06F7";
|
||
break;
|
||
case "\u0038":
|
||
res += "\u06F8";
|
||
break;
|
||
case "\u0039":
|
||
res += "\u06F9";
|
||
break;
|
||
default:
|
||
res += number[i];
|
||
}
|
||
}
|
||
return res;
|
||
};
|
||
//Convert Persian Numbers To English Numbers
|
||
const convertPeToEn = (number) => {
|
||
if (number == null || number == undefined) return "";
|
||
let res = "";
|
||
for (let i = 0; i < number.length; i++) {
|
||
switch (number[i]) {
|
||
case "\u06F0":
|
||
res += "\u0030";
|
||
break;
|
||
case "\u06F1":
|
||
res += "\u0031";
|
||
break;
|
||
case "\u06F2":
|
||
res += "\u0032";
|
||
break;
|
||
case "\u06F3":
|
||
res += "\u0033";
|
||
break;
|
||
case "\u06F4":
|
||
res += "\u0034";
|
||
break;
|
||
case "\u06F5":
|
||
res += "\u0035";
|
||
break;
|
||
case "\u06F6":
|
||
res += "\u0036";
|
||
break;
|
||
case "\u06F7":
|
||
res += "\u0037";
|
||
break;
|
||
case "\u06F8":
|
||
res += "\u0038";
|
||
break;
|
||
case "\u06F9":
|
||
res += "\u0039";
|
||
break;
|
||
default:
|
||
res += number[i];
|
||
}
|
||
}
|
||
return res;
|
||
};
|
||
|
||
const e2p = (s) => s.replace(/\d/g, (d) => "۰۱۲۳۴۵۶۷۸۹"[d]);
|
||
const e2a = (s) => s.replace(/\d/g, (d) => "٠١٢٣٤٥٦٧٨٩"[d]);
|
||
|
||
const p2e = (s) => s.replace(/[۰-۹]/g, (d) => "۰۱۲۳۴۵۶۷۸۹".indexOf(d));
|
||
const a2e = (s) => s.replace(/[٠-٩]/g, (d) => "٠١٢٣٤٥٦٧٨٩".indexOf(d));
|
||
|
||
const p2a = (s) =>
|
||
s.replace(/[۰-۹]/g, (d) => "٠١٢٣٤٥٦٧٨٩"["۰۱۲۳۴۵۶۷۸۹".indexOf(d)]);
|
||
const a2p = (s) =>
|
||
s.replace(/[٠-٩]/g, (d) => "۰۱۲۳۴۵۶۷۸۹"["٠١٢٣٤٥٦٧٨٩".indexOf(d)]);
|
||
|
||
export {
|
||
convert,
|
||
sliceNumber,
|
||
convertEnToPe,
|
||
convertPeToEn,
|
||
e2p,
|
||
e2a,
|
||
p2e,
|
||
a2e,
|
||
p2a,
|
||
a2p,
|
||
};
|